CakePHPのイベント処理の流れを少し追ってみたので、最近はまってるシーケンスダイアグラムをまた作成した。

とりあえず最初のイベントとしてDispatcher.beforeDispatchがあったので、それを追ってみました。前回作成したDispatcher::dispatchの処理の流れ 右上辺りにある、 “beforeDispatchのイベントが処理される” と書かれた箇所の詳細になります。どこまで詳しく書くべきか悩みましたが、リスナーに登録された具体的な処理の実行まで確認できるようにしたかったので結構大げさになってしまいました。機会があれば、このような具体的なふるまいの記述ではなく、一般的な流れを簡潔に表現したいと思います。

イベントシステムの導入で個別の処理のメンテナンスや拡張が容易になり、処理の結果をカプセル化した新たな役者の登場で、それぞれのキャラクターがより明確になったのではないでしょうか。その半面、仕方のないことですが直感的な見通しは悪くなってしまったかもしれません。

CakePHPのイベント処理の一例

CakePHPのイベント処理の一部をシーケンス図として表現したもの

“Dispatcher.beforeDispatch” という名前で登録されたイベントの処理において、実際には上の図の赤く塗った箇所、Dispatcher::parseParams, AssetDispatcher::beforeDispatch, CacheDispatcher::beforeDispatch が実行されます。もちろん、このほかにも適切に登録をおこなえばその処理も実行されますし、実行前の処理を detatch で取り除くことも可能です。開発者がコアのふるまいにクリーンに介入できることは大きな魅力のように思います。

もちろん、イベント駆動型にしたことで、それまでと比べると内部の処理はより複雑にならざるを得ず、たとえばAssetDispatcher::beforeFilterとCacheDispatcher::beforeFilterと同等の処理(Dispatcher::asset, Dispatcher::cached)の呼び出しは、2.1以前の処理だとたった一行で記述されていたりします。

// v2.1.5 における Dispatcher::asset と Dispatcher::cached の呼び出し
public function dispatch(....
    if ($this->asset($request->url, $response) || $this->cached($request->here())) {
        ....

ほぼこれと同じ処理をするために、上のようなことをやってるわけか。。。

普段はまず意識する必要ないことかもしれませんが、なかなか面白いですよね~。個人的にはCakeEventListener を実装したオブジェクトを登録させた場合に、CakeEventManagerからimplementedEventsで実装イベントを取得しに行くあたり、なかなか美味しいところではないかと。