We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Dispatcher exception handling

Soo, I am trying to handle 500 pages using dispatch:beforeException, see code:

 $di->setShared('dispatcher', function () use ($di) {
    /** @var Manager $eventsManager */
    $eventsManager = $di->getShared('eventsManager');

    $eventsManager->attach('dispatch:beforeException', function ($event, Dispatcher $dispatcher, $exception) use ($di)      {
            if ($exception instanceof \Phalcon\Mvc\Dispatcher\Exception) {
                switch ($exception->getCode()) {
                    case Phalcon\Mvc\Dispatcher::EXCEPTION_HANDLER_NOT_FOUND:
                    case Phalcon\Mvc\Dispatcher::EXCEPTION_ACTION_NOT_FOUND:
                        $action = ErrorController::ACTION_SHOW_404;

                        break;

                    default:
                        $action = ErrorController::ACTION_SHOW_500;
                }
            } else {
                $action = ErrorController::ACTION_SHOW_500;
            }

            $dispatcher->forward([
                'module'     => APP_MODULE,
                'controller' => 'error',
                'action'     => $action,
            ]);

            return false;
    });

    $dispatcher = new Dispatcher();
    $dispatcher->setEventsManager($eventsManager);

    return $dispatcher;
});

but the issue is that, when calling throw new \Exception('test') inside of controller action - everything is fine, but when calling it insade of initialize(), I get only blank page, and no error messages whatsoever.

Thinks I tested and excluded are:

  1. initialize() conflict on ErrorController - there it's empty public function initialize() { }, so it doesn't get called from ControllerBase which is having some action in there

  2. There are no code on 500 page, except settign status code(500) and using echo 500, so it doesn't throw exception itself

  3. 500 page and it's controller are super simple, they are not calling any kind of services, which could throw an exception

By checking dispatcher.zep, it should work as intended, but it doesn't... Really have no idea, what I am doing wrong.

When server throws 500 internal error on it's own, something has gone wild and thus cannot be catched by user level exceptions etc. For instance it could be syntax error, parse error or any kind of lower errors catched only by interpreter.

You need to define shutdown function on your index (FrontPageController) with native PHP register_shutdown_function().

Hi @janisbizkovkis $dispatcher->forward() don't suppot module but support namespace the rest of the code lucks fine

edited Aug '17

@stamster - it can be catched, see set_error_handler and set_exception_handler and register_shutdown_function

@emiliodeg - yep, it doesn't, but that option got ignored anyway. And namespace is the right one by checkig it. But still, I can't get why throwing exception in initialize() doesn't work, but throwing it in ControllerBase->idnexAction() it works... And most veirdly, on:

public function onShutDown() {
    if ($error = error_get_last()) {
        var_dump($error);
        die();
    }
}

$error is empty.

@stamster - it can be catched, see set_error_handler and set_exception_handler and register_shutdown_function

Isn't that what I wrote in my previous comment? I just don't see where you registered shutdown function in your code. Now you're saying that basically dispatcher is able to catch those level errors as well (not exceptions), w/o need to register shutdown function?