楽天Q&AにSabelについての質問が来ていたので回答した内容を下記に転載。
<?php class TransactionConfig extends Sabel_Container_Injection { public function configure() { $this->aspect("User")->advice("TransactionAdvice"); } } class TransactionAdvice { /** * @around movePoint */ public function processTransaction($invocation) { Sabel_DB_Transaction::activate(); # トランザクション有効化 try { $result = $invocation->proceed(); Sabel_DB_Transaction::commit(); # 正常終了 return $result; } catch (Exception $e) { Sabel_DB_Transaction::rollback(); # 例外が発生したらロールバック throw $e; } } } class User extends Sabel_DB_Model { public function movePoint() { $fromUser = MODEL("User", 1); if ($fromUser->point < $point) { throw new ... } else { $toUser = MODEL("User", 2); if ($toUser->isValid()) { ... } else { throw new ... } } } } ?>
として各クラスを、クラスパス上に配置します。
下記利用時のサンプルです。
$user = load("User", new TransactionConfig());
$user->movePoint();
とすれば、TransactionAdviceによるアスペクト処理が実行されます。
これは、@around movePoint としてアドバイスクラスにmovePointメソッドが指定されているので、movePoint()実行時の周辺(around)、つまりメソッドの実行前と実行後にアスペクトが介入します。