I am rewriting our company website in cakephp, and need to find a way to do the following:
- A user enters our site by using one
of the promotional alias URLS that
has been pregenerated for a specific
media advert ( magazine, web
promotion etc )
- The URL is checked against a
database of alias URLs, and if an
alias exists, then a specific
tracking code is written into the
session.
I have considered several options, none of which seem suitable for this purpose. They are:
- Putting the lookup script in the
beforeFilter() in appcontroller, so
that its included in every
controller. (Writes a session value
so it only perfoms once.)
- This option only works for existing contollers, and gives the
Cake 'missing controller' error if a
URL doesn't exist.
- Specific routes for each alias in
Routes.php - Works but there are
potentially hundreds of alias urls
added/removed regularly via admin
interface.
- Route all site URLs to their own
actions, and having an 'everything
else' rule, for the alias URLs that
maps to my lookup script. - Messy
and I lose the built in Cake
routing.
- Custom 404. - I don't want to
return 404's for these urls, as I
feel its bad practice unless they
really don't map to anything.
I really could do with a place in the application flow where I can put this lookup/tracking script, and I'm fairly new to cake so I'm stumped.
EDIT: Also, I know that a subfolder called say 'promo' would easily do this, but I have a lot of legacy URLS from our old site, that need handling too.
A very interesting question. I think I would use item #3. It's not really that messy -- after all, this typically is handled by the pages controller in my stuff. That's how I'd handle it - hardcode your routes to your controllers in routes.php, then have a matchall route that will work for your promo codes. This allows you to keep legacy URLs, as well as use a lot of the standard cake stuff (you probably will just have to explicitly state each of your controllers routes, not such a chore...) Additionally, it will let you do some cool stuff with 404 errors -- you can put some logic in there to try and figure out where they were trying to go, so you can superpower your 404's.
Note: I'm making an assumption that your promo URLs are in the form of "domain.com/advert-259" or something like that (i.e. no "domain.com/adverts/advert-259'). That would be just too simple :)
Hopefully, you can use the routing with some regex. Add this to your /config/routes.php and let me know if a different regex will help :)
$controllers = Configure::listObjects('controller');
foreach ($controllers as &$value)
{
$value = Inflector::underscore($value);
}
Router::connect('/:promo', array('controller' => 'promos', 'action' => 'process'), array('promo' => '(?!('.implode('|', $controllers).')\W+)[a-zA-Z\-_]+/?$'));
Now you can handle all your promo codes in PromosController::process()
.
Basically, it checks for a promo code in url, excluding those in the $controllers array (i.e. your regular routes won't be messed up).
Later on you might want to consider caching the value of Configure::listObjects()
depending on the speed of your app and your requirements.