search
top

Fancy URLs with Inflector::slug

Motivated by my recent tweet i thought i share my method of replacing the old SluggableBehavior with core functions.

Sometimes we have more than one model that uses slugs. For example: Tags, Posts, Categories. That’s why i add the following to AppModel which allows me to call it on any model.

function slugify($text) {
	return low(Inflector::slug($text, '-'));
}

But because i am lazy i just use one of the model callbacks to automate the “slugification(tm)”.

function beforeSave() {
	if ($this->hasField('slug') && isset($this->data[$this->alias][$this->displayField])) {
		$this->data[$this->alias]['slug'] = $this->slugify($this->data[$this->alias][$this->displayField]);
	}
}

So on any model that has a “slug” field in the associated table we always slugify the displayField (usually “name”) and keep it fresh. Dead simple.

2 Responses to “Fancy URLs with Inflector::slug”

  1. VoiDeT says:

    Thanks alot for this!
    I didn’t realise it could be so automagic :)
    However i did have to include a return true; in the beforeSave call.
    Also extended it to test if a custom slug has been included!

    Thanks again!

  2. Matt Huggins says:

    If the ’slug’ column is unique to your table, then you’ll need to do something more like the following (pseudoCode):

    function slugify($text) {
    $slug = low(Inflector::slug($text, ‘-’));
    $slugs = $this->find(’all’, array(
    ‘fields’ => array(’slug’),
    ‘conditions’ => array(’slug LIKE’ => ‘%’ . $slug),
    ));
    if ($slugs) {
    $slugs = Set::extract($slugs, “/{$this->alias}/slug”);
    // loop through $slugs while incrementing $i to see if current($slugs) === “$slug-$i”, returning the new value of $slug when they’re not equal.
    } else {
    return $slug;
    }
    }

Leave a Reply

top