Dealing with Alias URLs in CakePHP

2019-06-04 21:10发布

问题:

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 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.



回答2:

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.