Simple Sluggable Behavior for CakePHP
November 18, 2009 by Adam · Leave a Comment
For quite a while now pretty much the defacto standard for generating automagic slugs in CakePHP has been the Sluggable Behavior by Mariano Iglesias (mariano) in the Cake Bakery (http://bakery.cakephp.org/articles/view/sluggable-behavior). I’ve never quite gotten on with this behavior, it’s not that it doesn’t do what it says, it just seems like it uses a lot of code to do it, and I prefer all of my code to be as simple as possible.
I’ve been using my own Sluggable Behavior for a while, and today I found myself needing a little more customisation, I made a few changes and now it works in exactly the same way as Mariano Iglesias’s, but using less code (and CakePHP’s built in Inflector::slug). So here is my Sluggable Behavior.
<?php
class SluggableBehavior extends ModelBehavior {
/**
* Defaults
*
* @var array
* @access protected
*/
var $_defaults = array(
'seperator' => '-',
'label' => 'title',
'field' => 'slug',
'extension' => '.html',
'length' => 100,
'overwrite' => false
);
/**
* Initiate Sluggable behavior
*
* @param object $Model instance of model
* @param array $config array of configuration settings.
* @return void
* @access public
*/
function setup(&$Model, $config = array()) {
$settings = array_merge($this->_defaults, $config);
$this->_settings[$Model->alias] = $settings;
}
/**
* Before save method. Called before all saves
*
* Overriden to transparently manage creating and populating the slug field
*
* @param AppModel $Model Model instance
* @return boolean true to continue, false to abort the save
* @access public
*/
function beforeSave(&$Model) {
extract($this->_settings[$Model->alias]);
if(!empty($Model->data[$Model->alias][$Model->primaryKey]) && !$overwrite) {
return true;
}
if(!is_array($label) && empty($Model->data[$Model->alias][$label])) {
return false;
}
if(is_array($label)) {
$slug = '';
foreach($label as $key) {
$slug .= ife(!empty($slug), ' ', '') . $Model->data[$Model->alias][$key];
}
} else {
$slug = $Model->data[$Model->alias][$label];
}
$slug = Inflector::slug($slug, $seperator);
$slug = low($slug);
if(strlen($slug) > $length) {
$slug = substr($slug, 0, $length-1);
}
if(!empty($extension)) {
$slug = $slug . $extension;
}
$i = 1;
while($Model->find('count', array('conditions' => array($Model->alias . '.' . $field => $slug))) != 0) {
if (!preg_match ('/'.preg_quote($seperator).'{1}[0-9]+$/', $slug)) {
if(!empty($extension)) {
$slug = $slug . $seperator . ++$i . $extension;
} else {
$slug = $slug . $seperator . ++$i;
}
} else {
$slug = preg_replace('/[0-9]+$/', ++$i, $slug);
}
}
$Model->data[$Model->alias][$field] = $slug;
return parent::beforeSave($Model);
}
}
?>
Usage
var $actsAs = array(
'Sluggable' => array(
'label' => 'name',
'extension' => false
)
);
// or
var $actsAs = array('Sluggable');
Related posts: