Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

forward method in dispatch:beforeException event function does not trigger continuation of dispatcher loop

This is a sample dispatcher service registered with set method of \Phalcon\DI\FactoryDefault:

$eventsManager = new \Phalcon\Events\Manager();

$eventsManager->attach(
    "dispatch:beforeDispatchLoop",
    function (\Phalcon\Events\Event $event, $dispatcher) {

        throw new \Phalcon\Exception("Some unhandled exception.");
    }
);


$eventsManager->attach(
    "dispatch:beforeException",
    function($event, $dispatcher, $exception) {

        $dispatcher->forward(
            array(
                'controller' => 'error',
                'action'     => 'e404',
            )
        );

        return false;
    }
);


$dispatcher = new \Phalcon\Mvc\Dispatcher();

$dispatcher->setEventsManager($eventsManager);

return $dispatcher;

Expected Behaviour: After exception has been thrown, trigger dispatch:beforeException and handle dispatcher forward method invocation.

Actual Behaviour: After exception has been thrown,dispatch:beforeException event was triggered, but dispatcher forward method invocation is not handled.

Is this to be expected? I assume this has something to do with the Dispatcher Loop flag attribute _finished not evaluating to FALSE after invoking the forward method?

Is there a workaround to achieve the expected behaviour?



144
Accepted
answer
edited 9d ago

Still not sure, if the behaviour is to be expected, but i found a workaround, which satisfies my requirements:

Instead of throw new \Phalcon\Exception("Some unhandled exception."); once can set the controller name by $dispatcher->setControllerName to a string value of 0 (numeric should work too) in order to make sure, the controller class can never exist. A Phalcon\Mvc\Dispatcher\Exception exception will be thrown anyway, so this way it can be caught in the dispatch:beforeException event listener. The dispatcher loop finishes as expected.