CakePHP 3 the Way to Reach Controller Invoking part 3 of 3


This article is continued from CakePHP 3 the Way to Reach Controller Invoking part 2 of 3. webroot/index.php remains next 4 lines.

It is obvious that Request::createFromGlobals() creates request object from global variables like $_GET.

dispatch

dispatchEvent method raises event. And when the result of process after event occurred is response object, it ends process.

dispatchEvent

dispatchEvent method is not defined in Dispatcher, is defined in EventManagerTrait used by Dispathcer class.

this method calls dispatch method of EventManager. $event which is passed as argument is the instance of \Cake\Event\Event.

Let’s look into the constructor of \Cake\Event\Event

\Cake\Event\Event __construct

The argument of the constructor is 'Dispatcher.beforeDispatch' in this case.

It only assigns argument values to instance variables. In this case, $data is an associative array whose keys are 'request' and 'response'.

dispatch method of EventManager is executed with $event as argument.

EventManager dispatch

In dispatch method, listeners method is executed. The argument is $event->name(), it means 'Dispatcher.beforeDispatch'.. listeners method returns array of listeners which should be executed, in calling order.

listenres

Let’s look into prioritisedListeners method which is called in above code.

prioritisedListeners

There’s nothing difficult. It returns listener related to event key like 'Dispatcher.beforeDispatch' or 'Dispatcher.afterDispatch'.

And listeners method merges listeners in $globaListeners and $localListeners. EventManager is written in sort of singleton pattern, and we can separately use the instance for global use and the one for specific use. Actually in this case, $globalListeners is empty, then, the key in $localListeners added to $priorities and $priorities has no other keys. The key of listener is priority and $priorities is the array of int value, From low priority to high, and firstly global listener and secondly local listener, it generates listener array.

Back to dispatch method of EventManager, it call listener with _callListener method when isStopped is false, namely when the event is not ended.

_callListener

The value passed to $listener is handled as method name and executed. In this case, the method name is 'handle'. $event is the event created with new Event('Dispatcher.beforeDispatch'). $data[0] is request and $data[1] is response.

So, the return value of _callListener is handle($event, request, response) of filter object. Actually, $listener is executed for all the registered 4 filters.

handle method is not defined in each filter, is defined in the parent class, DispathcerFilter. Every filter we duscuss about inherits DispatcherFilter.

handle

Now, $event->name() returns 'Dispatcher.beforeDispatch', so $name become 'beforeDispatch'. That is, beforeDispatch defined in each class which executes handle method is executed.

Now, let’s look into beforeDispatch method in each class. In order of execution, the classes are AssetFilter, RoutingFilter, ControllerFactoryFilter. (I omit DebugBarFilter.)

AssetFilter beforeDispatch

It returns response when the request is for asset file. If request is for asset file, CakePHP 3 handle appropriate process like calling header method.

RoutingFilter beforeDispatch

It configures which controller should be used.

ControllerFactoryFilter beforeDispatch

It create controller instance and assigns it to $event->data['controller'].

Configured controller in above process will be invoked by invoke method in Dispathcer. On invoke method, the controller execute its process and render html.

At last, afterDispatch method is executed in dispatch method and process ends.