CakePHPのFilter強化
CakePHPの beforeFilter/afterFilter が大雑把すぎるので、一工夫。Railsみたいにメタプロ風+only/exceptを追加。
つまり、↓こうしたい。
class ShopController extends AppController{
var $beforeFilter
= array("doAlways",
"doAlmost"=>array(
"except"=>array("delete","order")
),
"doRare"=>array(
"only"=>array("cart")
)
);
function doAlways(){
$this->log("-----いつも必ず実行----",LOG_DEBUG);
}
function doAlmost(){
$this->log("-----ほとんどの場合実行----",LOG_DEBUG);
}
function doRare(){
$this->log("-----あるときだけ実行----",LOG_DEBUG);
}
var $beforeFilter
= array("doAlways",
"doAlmost"=>array(
"except"=>array("delete","order")
),
"doRare"=>array(
"only"=>array("cart")
)
);
function doAlways(){
$this->log("-----いつも必ず実行----",LOG_DEBUG);
}
function doAlmost(){
$this->log("-----ほとんどの場合実行----",LOG_DEBUG);
}
function doRare(){
$this->log("-----あるときだけ実行----",LOG_DEBUG);
}
AppController
オオモトのフィルタをこんな風に実装しておけば、あとはメタプログラミング風にフィルタを設定できるようになります。
<?php
class AppController extends Controller {
function beforeFilter(){
$this->_doFilter("beforeFilter");
}
function afterFilter(){
$this->_doFilter("afterFilter");
}
function beforeRender(){
$this->_doFilter("beforeRender");
}
function _doFilter($type){
$filters = $this->$type;
if (!empty($filters)) {
foreach ($filters as $key => $value) {
if( is_string($value) ){
$filter = $value;
if (is_callable(array($this,$filter)) ) {
$this->$filter();
}
}
else if(is_array($value)){
$filter = $key;
//$this->log("-------{$filter}----",LOG_DEBUG);
if( $value['only'] && $value['except'] ){
$this->log("{$type} confused....",LOG_DEBUG);
}
else if($value['only']){
if( in_array( $this->action, $value['only'] ) ){
if (is_callable(array($this,$filter)) ) {
$this->$filter();
}
}
}
else if($value['except']){
if( ! in_array( $this->action, $value['except'] ) ){
if (is_callable(array($this,$filter)) ) {
$this->$filter();
}
}
}
else{
$this->log("unexpeted filter defined",LOG_DEBUG);
}
}
}
}
}
}
?>
class AppController extends Controller {
function beforeFilter(){
$this->_doFilter("beforeFilter");
}
function afterFilter(){
$this->_doFilter("afterFilter");
}
function beforeRender(){
$this->_doFilter("beforeRender");
}
function _doFilter($type){
$filters = $this->$type;
if (!empty($filters)) {
foreach ($filters as $key => $value) {
if( is_string($value) ){
$filter = $value;
if (is_callable(array($this,$filter)) ) {
$this->$filter();
}
}
else if(is_array($value)){
$filter = $key;
//$this->log("-------{$filter}----",LOG_DEBUG);
if( $value['only'] && $value['except'] ){
$this->log("{$type} confused....",LOG_DEBUG);
}
else if($value['only']){
if( in_array( $this->action, $value['only'] ) ){
if (is_callable(array($this,$filter)) ) {
$this->$filter();
}
}
}
else if($value['except']){
if( ! in_array( $this->action, $value['except'] ) ){
if (is_callable(array($this,$filter)) ) {
$this->$filter();
}
}
}
else{
$this->log("unexpeted filter defined",LOG_DEBUG);
}
}
}
}
}
}
?>
その前に、ちょっと改造
CakePHP 1.2.0.5427alphaでは、$beforeFilterだけは、CakePHPが認識してくれる(してしまう)。
var $beforeFilter = array("doA","doB");
というフィルタメソッドの複数指定が可能。というモノ。($afterFilterと、$beforeRenderに対しては、今のところ実装がありません。)
しかし、こんな大雑把なフィルタ機能では使い道がナイと思う。
ので、削除します。このあたりは、今後Cakeのバージョンが上がった時に干渉しやすいところだと思うので、お気をつけて。
※↑自己レス:
ムリにかっこつけないで、変数名がCakeと干渉しないように変えればいいだけかw。$bfとか、$_beforeFilterとか。そしたら、下の改造はいらないです。
■/cake/dispatcher.php
line:380あたり。function start()
/*
このifブロックをコメントアウト
if (!empty($controller->beforeFilter)) {
if (is_array($controller->beforeFilter)) {
:
}
:
}
*/
/*
このifブロックをコメントアウト
if (!empty($controller->beforeFilter)) {
if (is_array($controller->beforeFilter)) {
:
}
:
}
*/

