PHPでFilterChainを実装してみた

[PHP] : PHPでFilterChainを実装してみた

説明

前処理と後処理を各FilterClassに実装してFilterをChainさせます。
処理の順番としては
■前処理(prefilter)
filterA → filterB → filterC
■後処理(postfilter)
filterC → filterB → filterA
というように後処理は前処理と逆に行われます。

FilterChainクラス



class FilterManager {

private static $_filters = array();
private static $_index = 0;

private function __construct(){}

public function build( array $filters ) {
    foreach( $filters as $filter ) {
        $filter_name = ucfirst( $filter ) . 'Filter';
        $file_name = $class_name . '.php';
        //require_once( './Filter.php' );
        require_once( $file_name );
        self::add( $filter_name );
    }
}

static private function add( $filter ) {
    self::$_filters[] = $filter;
}

static public function execute() {
    // prefilter
    foreach( self::$_filters as $filter ) {
        $filter::prefilter();
        ++self::$_index;
    }

    // postfilter
    foreach( array_reverse( self::$_filters ) as $filter ) {
        $filter::postfilter();
        --self::$_index;
    }

}

static public function getCurrentFilter() {
    return self::$_filters[ self::$_index ];
}

}

FIlterChainを構築するbuildメソッド
FilterChainにFilterを追加するaddメソッド
FilterChainを実行するexecuteメソッド
現在実行中のFilterを取得するgetCurrentFilterメソッド
を定義します。

Filterのinterface



interface Filter {
static public function prefilter();
static public function postfilter();
}

prefilter,postfilterのメソッドを定義します。

各Filterの定義


class ViewFilter implements Filter {
static public function prefilter() {
    echo "View Prefilter \n";
}
static public function postfilter() {
    echo "View Postfilter \n";
}
}

class ActionFilter implements Filter {
static public function prefilter() {
    echo "Action Prefilter \n";
}
static public function postfilter() {
    echo "Action Postfilter \n";
}
}

本来はprefilter,postfilterにそれぞれ的確な内容を記述すべきですが、
今はサンプルなので適当にechoだけ書いておきます。

client



/* client */
require_once( './FilterManager.php' );

//呼び出しfilterの決定
$filters = array( 'view', 'action' );

//filterのbuildと実行
FilterManager::build( $filters );
FilterManager::execute();

FilterChainを実行してくれるFilterManagerを呼び出し、配列形式で利用したいFilterクラス名を渡します。

実行結果

View Prefilter 
Action Prefilter 
Action Postfilter 
View Postfilter

prefilterとpostfilterの実行の順番が逆になっていることが分かります。