Created
November 13, 2012 23:04
-
-
Save gapple/4069038 to your computer and use it in GitHub Desktop.
CakePHP routing based on slug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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', | |
) | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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