Skip to content

Instantly share code, notes, and snippets.

@gapple
Created November 13, 2012 23:04
Show Gist options
  • Save gapple/4069038 to your computer and use it in GitHub Desktop.
Save gapple/4069038 to your computer and use it in GitHub Desktop.
CakePHP routing based on slug
<?php
App::import('Lib', 'routes/SluggableRoute');
Router::connect(
'/path-alias/:slug/*',
array(
'controller' => 'controller_name',
'action' => 'action_name',
'model' => 'ModelName',
),
array(
'slug' => '[\w-]+',
'routeClass' => 'SluggableRoute',
)
);
<?php
/**
* Handle routes with a slug component from a model attribute.
*
* @see https://gist.github.com/4069038
*/
class SluggableRoute extends CakeRoute {
protected $cache_items = null;
function match($url) {
// CakeRoute::match() expects model to be provided in $url to determine
// the correct route, but controller & action are enough if multiple
// models don't use the same route.
$url['model'] = $this->defaults['model'];
if ($url['action'] != $this->defaults['action'] || $url['controller'] != $this->defaults['controller']) {
return false;
}
// if an item's id was passed in instead of it's slug, translate it.
if (!isset($url['slug']) && isset($url[0])) {
$model = $url['model'];
$id = $url[0];
if (is_null($this->cache_items)) {
$this->cache_items = Cache::read('SluggableRoute.' . $model);
}
if (!empty($this->cache_items) && false !== ($slug = array_search($id, $this->cache_items))) {
// $slug already set in conditional
}
else {
App::import('Model', $model);
list($plugin, $model) = pluginSplit($model);
$Model = new $model;
$item = $Model->find('first', array(
'fields' => array('slug'),
'conditions' => array(
$Model->alias . '.id' => $id,
),
'contain' => array(),
'recursive' => -1,
));
if (empty($item)) {
return false;
}
$slug = $item[$Model->alias]['slug'];
if (empty($this->cache_items)) {
$this->cache_items = array();
}
$this->cache_items[$slug] = $id;
Cache::write('SluggableRoute.' . $model, $this->cache_items);
}
$url['slug'] = $slug;
unset($url[0]);
}
return parent::match($url);
}
function parse($url) {
$params = parent::parse($url);
if (empty($params) || empty($params['model']) || empty($params['slug'])) {
return false;
}
$model = $params['model'];
$slug = $params['slug'];
if (is_null($this->cache_items)) {
$this->cache_items = Cache::read('SluggableRoute.' . $model);
}
if (!empty($this->cache_items) && array_key_exists($slug, $this->cache_items)) {
$id = $this->cache_items[$slug];
}
else {
App::import('Model', $model);
list($plugin, $model) = pluginSplit($model);
$Model = new $model();
$item = $Model->find('first', array(
'fields' => array('id', 'slug'),
'conditions' => array(
$Model->alias . '.slug' => $slug,
),
'contain' => array(),
'recursive' => -1,
));
$id = ($item) ? $item[$Model->alias]['id'] : false;
if (empty($this->cache_items)) {
$this->cache_items = array();
}
$this->cache_items[$slug] = $id;
Cache::write('SluggableRoute.' . $model, $this->cache_items);
}
if (!$id) {
return false;
}
$params['pass'] = array(
$id,
);
return $params;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment