The Phalcon\Mvc\Dispatcher is the component responsible for instantiating controllers and executing the required actions on them in an MVC application. Dispatching is the process of taking the request object, extracting the module name, controller name, action name, and optional parameters contained in it, and then instantiating a controller and calling an action of that controller.
Calls an action method with a handler and parameters
Process the results of the router by calling into the appropriate controller action(s) including any routing data or injected parameters. Returns the dispatched handler class (the Controller for Mvc dispatching or a Task for CLI dispatching) or false if an exception occurred and the operation was stopped by returning false in the exception handler. Throws an Exception if any uncaught or unhandled exception occurs during the dispatcher process.
Forwards the execution flow to another controller/action.
Sets the latest returned value by an action manually
Check if the current executed action was forwarded by another one
This is an important process that has much to do with the MVC flow itself, especially with the controller part. The work occurs within the controller dispatcher. The controller files are read, loaded, and instantiated. Then the required actions are executed. If an action forwards the flow to another controller/action, the controller dispatcher starts again. To better illustrate this, the following example shows approximately the process performed within the Phalcon\Mvc\Dispatcher component.
In the code above, we are calculating the controller name, instantiate it and call the relevant action. After that we finish the loop. The example is very simplified and lacks validations, filters and additional checks, but it demonstrates the normal flow of operation within the dispatcher.
The dispatch loop allows you to forward the execution flow to another controller/action. This is very useful in situations when checking if the user has access to certain areas, and if not allowed to be forwarded to other controllers and actions, thus allowing you to reuse code.
NOTE: Keep in mind that performing a forward is not the same as making an HTTP redirect. Although they produce the same result, performing a forward will not reload the current page, while the HTTP redirect needs two requests to complete the process.
Forward flow to another action in the current controller, passing parameters
A forward action accepts the following parameters:
A valid controller name to forward to.
A valid action name to forward to.
An array of parameters for the action.
A valid namespace name where the controller is part of.
By using events or hook points available by the Phalcon\Mvc\Dispatcher, you can easily adjust your application to accept any URL schema that suits your application. This is particularly useful when upgrading your application and want to transform some legacy URLs. For instance, you might want your URLs to be:
The viewAction receives an instance of the model Invoices. If you try to execute this method without any checks and manipulations, the call will fail. You can however inspect the passed parameters before the dispatch loop and manipulate the parameters accordingly.
In the example above, we get the controller class and active method from the dispatcher. Looping through the parameters, we use reflection to check the method to be executed. We calculate the model name and also check if the parameter is expecting a model name. If yes, we override the parameter by passing the model found. If an exception was thrown, we can handle that accordingly, for instance if the class or action do not exist or the record has not been found.
The above example has been simplified. You can adjust it according to your needs and inject any kind of dependency or model to an action before it gets executed.
The dispatcher also comes with an option to handle this internally for all models passed into a controller action by using the Phalcon\Mvc\Model\Binder object.
NOTE: The Phalcon\Mvc\Model\Binder component uses PHP’s Reflection API internally, which consumes additional processing cycles. For that reason, it has the ability to use a cache instance or a cache service name. To use this feature, you can pass the cache service name or instance as the second argument in the setModelBinder() method or by just passing the cache instance in the Binder constructor.
In the InvoicesController we will define which model the controller is associated with. This is done by implementing the Phalcon\Mvc\Model\Binder\BindableInterface, which will make the getModelName() method available. This method is used to return the model name. It can return string with just one model name or an associative array with the key is the parameter name.
NOTE: Only exceptions produced by the dispatcher and exceptions produced in the executed action notify the beforeException events. Exceptions produced in listeners or controller events are redirected to the latest try/catch.
Phalcon\Mvc\Dispatcher is able to send events to a Manager if it is present. Events are triggered using the type dispatch. Some events when returning boolean false could stop the active operation. The following events are supported:
After models are bound but before executing route
After executing the controller/action method.
After exiting the dispatch loop
After executing the controller/action method.
Allow to globally initialize the controller in the request
After entering in the dispatch loop. The Dispatcher only knows the information passed by the Router.
Before entering in the dispatch loop. The Dispatcher only knows the information passed by the Router.
Before the dispatcher throws any exception
Before executing the controller/action method. The Dispatcher has initialized the controller and knows if the action exist.
Before forwarding to a controller/action method. (MVC Dispatcher)
when the action was not found in the controller
The INVO sample application, demonstrates how you can take advantage of dispatching events, implementing a security filter with Acl
The following example demonstrates how to attach listeners to this component:
* Dispatches a handle action taking into account the routing parameters
* Forwards the execution flow to another controller/action
* Gets last dispatched action name
* Gets the default action suffix
* Returns the active controller in the dispatcher
* Gets last dispatched controller name
* Gets the default handler suffix
* Returns the latest dispatched controller
* Gets a param by its name or numeric index
* @param string|array filters
* Gets action params
* Returns value returned by the latest dispatched action
* Check if a param exists
* Checks if the dispatch loop is finished or has more pendent
* controllers/tasks to dispatch
* Sets the action name to be dispatched
* Sets the default action suffix
* Sets the default controller suffix
* Sets the controller name to be dispatched
* Sets the default action name
* Sets the default controller name
* Sets the default namespace
* Sets the default suffix for the handler
* Sets the module name which the application belongs to
* Sets the namespace which the controller belongs to
* Set a param by its name or numeric index
* @param mixed value
* Sets action params to be dispatched