5
\$\begingroup\$

I want to direct all requests that haven't got a valid controller action to my custom page controller.

I.e. I want /pages/new & /users/login etc to work correctly, but a request for /foo or /foo/bar should be directed to /pages/display/$path.

The following code works, but I'm pretty certain I'm not doing something the right way(tm).

// In app/Config/routes.php
Router::connect('/', array('controller' => 'pages', 'action' => 'displayHome'));

$controllerList = App::objects('controller');
foreach ($controllerList as $controller) {
    $contstr = substr($controller, 0, strlen($controller)-10);
    $contstr = Inflector::tableize($contstr);
    if($contstr != 'app') {
        Router::connect('/'. $contstr, array('controller'=>$contstr));
        Router::connect('/'. $contstr .'/:action', array('controller'=>$contstr));
        Router::connect('/'. $contstr .'/:action/*', array('controller'=>$contstr));

        // FIXME: Check if admin routing is set
        Router::connect('/admin/'. $contstr, array('controller'=>$contstr, 'admin'=>true));
        Router::connect('/admin/'. $contstr .'/:action', array('controller'=>$contstr, 'admin'=>true));
        Router::connect('/admin/'. $contstr .'/:action/*', array('controller'=>$contstr, 'admin'=>true));
    }
}

Router::connect('/**', array('controller'=>'pages', 'action'=>'display'));

Would someone please be able to review this and tell me if this is okay/horribly wrong?

\$\endgroup\$

1 Answer 1

6
\$\begingroup\$

Use a pattern

The general principle is fine, though it won't handle plugin routes (which I assume isn't a problem)

However instead of a loop (and therefore defining 6 routes per controller) a parameter for the controller name can be used which will be more concise and likely overall more performant. The code could be rewritten like this:

// Define a home route
Router::connect('/', array('controller' => 'pages', 'action' => 'displayHome'));

// Generate a regex-like controller name pattern (e.g. "posts|comments|users")
$controllerList = App::objects('controller');
$controllerList = array_map(function($c) {
    return Inflector::underscore(substr($c, 0, strlen($c)-10);
}, $controllerList));
$controllerList = array_filter($controllerList, function ($c) {
    return $c !== 'app'
});
$controller = implode('|', $controllerList);

// Define normal routes
$params = array('controller' => $controller);
Router::connect('/:controller', $params);
Router::connect('/:controller/:action', $params);
Router::connect('/:controller/:action/*', $params);

// Define admin routes
$params += array('admin' => true, 'prefix' => 'admin');
Router::connect('/admin/:controller', $params);
Router::connect('/admin/:controller/:action', $params);
Router::connect('/admin/:controller/:action/*', $params);

// Define catchall
Router::connect('/**', array('controller'=>'pages', 'action'=>'display'));

In this way there are 8 routes in total, no matter how many controllers there are in the application.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.