Let's say you have an app which has some promo codes, like so:
http://example.com/get-free-stuff-23999
or simply:
http://example.com/whatever
How do you tell cake this is not a controller and how to avoid the "missing controller" error? Answer: RegEx!
You might think it's very simple to do something like this. Like so:
Router::connect ( '/:promo', array ( 'controller' => 'codes', 'action' => 'process' ), array ( 'promo' => '[a-zA-Z\-_]+' ) );
But there's a problem with that. Assuming you also have an ArticlesController, what happens when someone enters:
http://example.com/articles
Bad stuff. And you don't want to enter a special route for all controllers, don't you?
Here's something I came up with, it seems to be working but no guarantees..
$controllers = Cache::read('controllers_list'); if ($controllers === false) { $controllers = Configure::listObjects('controller'); foreach ($controllers as &$value) { $value = Inflector::underscore($value); } $controllers = implode('|', $controllers); Cache::write('controllers_list', $controllers); } Router::connect ( '/:promo', array ( 'controller' => 'codes', 'action' => 'process' ), array ( 'promo' => '(?!('.$controllers.')\W+)[a-zA-Z\-_]+/?$' ) );
Easy right? Simple negative lookahead to make sure we're not grabbing all the routes including other controllers, and a simple RegEx to match all the characters we want to use in our "promo code".
I assume there are some limitations to this method, but it might also be useful to someone.
Happy baking!
Article comments — View · Add
I actually did this to answer someone's question on StackOverflow, and I did recommend caching. I sure hope he did it... :)