patternphpMinor
CakePHP 2.x Custom PagesController & Routing
Viewed 0 times
customcakephproutingpagescontroller
Problem
I want to direct all requests that haven't got a valid controller action to my custom page controller.
I.e. I want
The following code works, but I'm pretty certain I'm not doing something the right way(tm).
Would someone please be able to review this and tell me if this is okay/horribly wrong?
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?
Solution
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:
In this way there are 8 routes in total, no matter how many controllers there are in the application.
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.
Code Snippets
// 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'));Context
StackExchange Code Review Q#19219, answer score: 6
Revisions (0)
No revisions yet.