AOPが実装されれば
・・・以下のようなInterceptorが「components/」ディレクトリ以下のクラスにかけれるようになります。
class TraceInterceptor { function invoke(&$invocation) { // Interceptしたインスタンスを取得 $instance =& $invocation->getInstance(); $className = get_class($instance); // Interceptしたメソッド名を取得 $methodName = $invocation->getMethodName(); // Interceptしたメソッドの引数を取得(この例では出番はないですが・・・) $arguments =& $invocation->getArguments(); // 前処理(Before Advice) $log =& LogFactory::getLog(); $log->trace("${className}#${methodName}の前処理が実行されました", "${className}#${methodName}"); $result = $invocation->proceed(); // 後処理(After Advice) $log->trace("${className}#${methodName}の後処理が実行されました", "${className}#${methodName}"); } }
「$invocation->proceed()」でInterceptした元の関数が実行されるので、その前後でしたい処理をするという感じですね。(MapleのFilterChainの仕組みをご存知の方はほぼ同じだと思っていただけるかと)
ぱっとみて気が付いた方はいらっしゃると思いますが、Seasar2のAOPそのままです。なんとかそれを実現しようと思ってます。
組み立て具合もSeasar2と同じように以下のようになります。
- まず、InterceptorクラスのインスタンスをDIContainerに登録(dicon.iniに記述というとですね)
- 登録したコンポーネント(Intercepter)を特定のクラスのメソッドに関連付ける(これもdicon.iniで行う。最終的にはHawkさんのDI2を拡張して「apect://」みたいな指定になるといいですね。)
- 関連付けされた特定のクラスのメソッドが実行されるとInterceptorが発動する
Seasar2は本当に参考になります。DI+AOPという組み合わせであれば、PHP4でもなんとかなりそうです。というか、DI+AOPという組み合わせでないと使い物にならないと思います。
Seasar2はやりたいことを最短距離でやるという思想を感じるので、ほんとうにしっくりきます。おそらく他のフレームワークとかももともとはそうだったんだろうけど、いろいろ機能追加を続けた結果、もともとは何をめざしていたの?と思うようなものが多いので。