tags:

views:

728

answers:

2

I am rewriting our company website in cakephp, and need to find a way to do the following:

  1. 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 )
  2. 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:

  1. 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.
  2. Specific routes for each alias in Routes.php - Works but there are potentially hundreds of alias urls added/removed regularly via admin interface.
  3. 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.
  4. 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.

+1  A: 

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.

Travis Leleu
You don't have to state each controllers routes, you just have to state each controller - like '/my_controller/:action/'
gnud
gnud, can you post an example route please? I'm unsure of that syntax. Thanks.
Pickledegg
Try Router::connect('/mycontroller/:action/*', array('controller' =>'mycontroller'));Keep in mind that now you have to specify an action for the route to kick in, just going to /mycontroller/ won't work (IIRC)
gnud
great thanks! would i have to do the same for the pages controller though?
Pickledegg
+3  A: 

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.

dr Hannibal Lecter
thanks for this Dr Lecter. I have some reading to do on routes I think. In the meantime try not to kill anyone.
Pickledegg
I only kill the impolite :-)
dr Hannibal Lecter