Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

PHPでFilterChainを実装してみた

説明

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

FilterChainクラス

<?php

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

<?php

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

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

各Filterの定義

<?php
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

<?php

/* 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の実行の順番が逆になっていることが分かります。