runkitでAOP風味
お遊び的にrunkitを使ってAOPするサンプルを作ってみました。
<?php class Example { public function foo() { return "foo"; } } class Logger { public static function debug($message) { Logger::log('debug', $message); } public static function info($message) { Logger::log('info' , $message); } public static function warn($message) { Logger::log('warn' , $message); } public static function error($message) { Logger::log('error' , $message); } public static function fatal($message) { Logger::log('fatal' , $message); } private static function log($level, $message) { printf('[%s]:%s<br>', $level, $message); } } $obj = new Example(); echo $obj->foo(); echo '<hr>'; // fooメソッドをbarメソッドに改名 runkit_method_rename( 'Example', 'foo', 'bar' ); // 新たにfooメソッドを追加 // 元々のfooメソッド(現在のbarメソッド)を呼び出すが、 // その前後でデバッグ情報を表示 runkit_method_add( 'Example', 'foo', null, ' Logger::debug("start foo()"); $ret = $this->bar(); Logger::debug("end foo()"); return $ret; ', RUNKIT_ACC_PUBLIC ); $obj = new Example(); echo $obj->foo();
staticメソッド(Logger::debug)の呼び出しだけですが、面白いですね、これ。
作っていて思ったんですが、AOPの「元のスクリプトに影響を与えないで、横断的関心事を追加する」という部分は充分達成できそうですね。埋め込み方法が特殊(PHPスクリプトをそのまま渡す)なので、s2containerみたいにその辺をうまく隠蔽できると面白そうです :-)