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

Difference between setDefaults and notFound

What is the difference between Phalcon\Mvc\Router::setDefaults() and Phalcon\Mvc\Router::notFound()? Both of them sets an array of default paths the router will use if route is missing.



32.4k
edited Mar '14

May be this is it: "Since none route is matched the router passes empty values to the dispatcher, and the dispatcher is using the default controller/index to address the request. In 1.0.0 you can set what paths must be used if none existing route is matched:

$router->notFound(array('controller' => 'errors', 'action' => 'notfound404')); 

https://github.com/phalcon/cphalcon/issues/446#issuecomment-14251200



29.4k
edited Mar '14

But there's no difference

$router->setDefaults(array('controller' => 'errors', 'action' => 'notfound404')); 

I think notFound make sense if framework automatically sets the correct 404 response header regardless of page content, otherwise it's pointless.



29.4k

Just checked it. Status is "200 OK" in both cases. Setting the response header is left up on the developers.



98.9k
Accepted
answer

The new 'not-found paths' is different to defaults. 'Defaults' is intended to fill paths that aren't defined in every route added to the router:

$router = new Phalcon\Mvc\Router(false);

$router->setDefaultNamespace('App\Controllers');

$router->add('/app/index', array(
    'controller' => 'index',
    'action' => 'index'
));

$router->add('/app/robots', array(
    'controller' => 'robots',
    'action' => 'index'
));

Both routes have by default the namespace App\Controllers without explicitly set them manually. Consider the following example, where 'defaults' are used as 'not found' routes:


$router = new Phalcon\Mvc\Router(false);

$router->setDefaults(array(
    'controller' => 'errors',
    'action' => 'notFound404'
));

$router->add('/index', array(
    'module' => 'frontend',
    'controller' => 'index',
));

$router->add('/admin/index', array(
    'module' => 'backend',
    'controller' => 'index'
));

The path 'action' is not defined because we expect to use the default 'index', but as we're using the defaults it will fill it with 'notFound404' instead of 'index', so when we access /index the paths returned by the router will be: module => frontend, 'controller' => 'index', 'action' => 'notFound404' that is wrong.

This is fixed using the notFound method:


$router = new Phalcon\Mvc\Router(false);

$router->notFound(array(
    'controller' => 'errors',
    'action' => 'notFound404'
));

$router->add('/index', array(
    'module' => 'frontend',
    'controller' => 'index',
));

$router->add('/admin/index', array(
    'module' => 'backend',
    'controller' => 'index'
));

Note that notFound method is not a final solution for a 'not-found' handler, Let's pretend we define the following routes:


$router = new Phalcon\Mvc\Router(false);

$router->add('/:controller', array(
    'module' => 'frontend',
    'controller' => 1
));

$router->add('/:controller/:action/:params', array(
    'module' => 'frontend',
    'controller' => 1,
    'action' => 2,
    'params' => 3
));

These routes match almost every URI passed to the application, there're no way that the router doesn't match a route if they're defined in this way, so implement 'notFound' paths are useless here.

If /products/save/1 is passed as route it passes {controller => products, action => save, params => [1] }

The dispatcher needs to execute the route but it couldn't exists, so that's why you need to implement a notFound handler in the dispatcher:

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

    if ($event->getType() == 'beforeException') {
        switch ($exception->getCode()) {
            case Phalcon\Dispatcher::EXCEPTION_HANDLER_NOT_FOUND:
            case Phalcon\Dispatcher::EXCEPTION_ACTION_NOT_FOUND:
                $dispatcher->forward(array(
                    'controller' => 'errors',
                    'action' => 'show404'
                ));
                return false;
        }
    }
});

Maybe $router->notFound() should catch EXCEPTION_ACTION_NOT_FOUND also?



100

How do you setup/attach the eventsManager for this? I'm trying to implement this very thing!