Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

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みたいにその辺をうまく隠蔽できると面白そうです :-)