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?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Dec 2, 2012 at 4:15
\$\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.

answered Oct 7, 2013 at 8:52
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.