Why Dispatcher::forward() does not invoke dispatcher loop or part of it? And what exactley happens when forward() invoked? Thanks.
|
Jul '13 |
3 |
1493 |
1 |
Why Dispatcher::forward() does not invoke dispatcher loop or part of it? And what exactley happens when forward() invoked? Thanks.
As far as i understood how the dispatcher works, Dispatcher::forward() wont invoke the loop, it just will forward to another controller if the dispatcher is already looping.
Its Behaviour is to forward the current http request from on controller, to another controller.
Can you give a code snippet of what you are doing ?
On all of them i can give an answer by myself (after day of tests%)) not fully, but can. And just for clear and googles I wish to see some internal behavior explanations. That would be better than mine. Cause I can't answer WHY it's works exactly that way. No time to read C :(
Everything starts in the router:
The router parses the URI according to the one passed to it, ($_GET['_url'], $_SERVER['REQUEST_URI'], others) After this handling the router pass the processed module/namespace/controller/action to the dispatcher:
$dispatcher->setControllerName($router->getControllerName());
$dispatcher->setActionName($router->getActionName());
$dispatcher->setParams($router->getParams());
When $dispatcher->dispatch() is executed, this starts a dispatch loop which basically uses a flag variable ($finished) in the dispatcher to know if there are remaining actions to dispatch:
$this->_finished = false;
while (!$this->_finished) {
//execute actions
$this->_finished = true;
}
The dispatch loop allows the developer to perform additional forwards, this means that $this->_finished is reset to false making the dispatcher loop again and execute the forwarded action.
$eventsManager->fire('dispatch:beforeDispatchLoop');
$this->_finished = false;
while (!$this->_finished) {
$eventsManager->fire('dispatch:beforeDispatch');
if ($this->_finished==false) {
continue;
}
$controllerName = $this->_controllerName;
$actionName = $this->_actionName;
$params = $this->_params;
/**
* Controllers are instantiated via the DI
* This ensures that only one instance will be created
* in the application;
*/
$controller = $di->getShared($controllerName . 'Controller');
if (!method_exists($controller, $action . 'Action')) {
throw new Exception('404 not found');
}
$eventsManager->fire('dispatch:beforeExecuteAction');
if ($this->_finished==false) {
continue;
}
$controller->$action($params);
$eventsManager->fire('dispatch:afterExecuteAction');
if ($this->_finished==false) {
continue;
}
$eventsManager->fire('dispatch:afterDispatchLoop');
if ($this->_finished==false) {
continue;
}
$this->_finished = true;
}
When you make a forward the internal $this->_finished is changed to false, this is detected and the dispatch loop iterates again:
public function forward($forward)
{
if (isset($forward['controller'])) {
$this->_controllerName = $forward['controller'];
}
if (isset($forward['action'])) {
$this->_actionName = $forward['action'];
}
$this->_finished = false;
}