Table of Contents
中編に続いて処理内容を見ていきます。 webroot/index.php
に残されたのは次の4行でした。
Request::createFromGlobals()
はメソッド名から明らかですが、 グローバル変数 $_GET
等 からリクエストオブジェクを作成します。
dispatch
dispatchEvent
でイベントを発生させています。 そしてイベントが発生した後の処理結果がレスポンスオブジェクトになっていたら終了します。
dispatchEvent
dispatchEvent
は、 Dispatcher
では定義されておらず、 Dispathcer
で使用されている EventManagerTrait
で定義されています。
このメソッドが更に EventManager
の dispatch
を呼んでいます。 引数として渡される $event
は CakeEventEvent
のインスタンスです。
CakeEventEvent
のコンストラクタを確認します。
CakeEventEvent
__construct
コンストラクタの引数は、 'Dispatcher.beforeDispatch'
になります。
インスタンス変数に引数の値を格納しているだけでした。 今回 $data
は 'request'
と 'response'
をキーにもつ連想配列になります。
作成された $event
を引数にして EventManager
の dispatch
メソッド が実行されます。
EventManager
dispatch
dispatch
の中で listeners
メソッドが実行されます。 引数は $event->name()
ですので 'Dispatcher.beforeDispatch'
です。
listeners
は 呼び出されるべきリスナを、呼び出される順序で配列にして返します。
listenres
呼び出されているメソッド prioritisedListeners
の中身を見てみます。
prioritisedListeners
とくに難しいことは行っていません。 イベントキー すなわち 'Dispatcher.beforeDispatch'
や 'Dispatcher.afterDispatch'
に関係するリスナを返すメソッドです。
そして listeners
では $globaListeners
と $localListeners
のリスナーをマージしています。 Eventmanager
はシングルトンっぽいつくりになっていて、 グローバルに扱えるインスタンスと、 個別の用途に使うインスタンスを分けることができるようになっています。 実際のところ今回の処理では $globalListeners
が空なので、 $localListeners
のキーがそのまま $priorities
に入ります。 リスナのキーは優先度(priority) ですので、 $priorities
には int
型 の 優先度の配列になります。
優先度の数値が低いものから順に、そしてグローバルリスナを優先して、リスナの配列を作成しています。
EventManager
の dispatch
に戻り、 isStopped
が false
の場合、すなわちイベントが終了していない場合に _callListener
でリスナを呼び出します。
_callListener
$listener
に渡された値がメソッドの名前になり、実行されます。 実際に渡されるメソッド名は 'handle'
です。 $event
は new Event('Dispatcher.beforeDispatch')
で作成されたイベントです。 $data[0]
が request
で $data[1]
が response
です。
すると _callListener
の 返り値 は フィルタオブジェクト の handle($event, request, response)
になります。 実際のところ、 登録された 4つのフィルタについて $listener
が実行されます。
handle
メソッドは それぞれのフィルタではなく、 その親クラスの DispathcerFilter
で定義されています。 今まで出てきたすべてのフィルタは DispatcherFilter
を継承していました。
handle
今、 $event->name()
は 'Dispatcher.beforeDispatch'
になりますから、 $name
には 'beforeDispatch'
が入ります。 つまり、 handle
を実行するそれぞれのクラスで定義された beforeDispatch
メソッド が実行されることになります。
それぞれのクラスの beforeDispatch
を見てみましょう。
実行される順で見ると、 AssetFilter
, RoutingFilter
, ControllerFactoryFilter
です。 (DebugBarFilter
は省略します。)
AssetFilter
beforeDispatch
Asset ファイル のリクエストだった場合にレスポンスを返します。 Asset ファイル だった場合、 header
メソッド を呼び出したりして適宜処理をします。
RoutingFilter
beforeDispatch
どのコントローラを使うべきなのかを指定しています。
ControllerFactoryFilter
beforeDispatch
コントローラをインスタンス化して $event->data['controller']
に代入しています。
このようにして設定されたコントローラが、 Dispatcher
の invoke
メソッド で実行されます。 invoke
が実行されると、 Controller
が render
まで実行します。 そして html の生成まで行われます。
あとは、 dispatch
メソッド のところで afterDispatch
を実行して終わります。