esjay
esjay

Reputation: 165

CakePHP Routes.php for Slugs

I am trying to get my CakePHP app to use slugs instead of ids. I have read several tutorials and the CakePHP book about it, but I must be missing something simple.

My table has a "slug" field that I want to use for the URL instead of the default id.

I changed my ItemsController view to this:

public function view($slug = null) {
    if (!$this->Item->exists($slug)) {
        throw new NotFoundException(__('Invalid item'));
    }

    $this->set('item', $this->Item->findBySlug($slug));
}

And added this to my routes.php

Router::connect(
'/items/:slug', 
array('controller' => 'items', 'action'=>'view'),
array('pass'=>array('slug'))
);

Yet I still get "Invalid Item, requested address not found..." when going to:

mycakeapp/items/slug-value

However, if I change everything from 'slug' to 'id' then the URL:

mycakeapp/items/id-value

works just fine

Can someone help me? Thanks in advance.

Upvotes: 0

Views: 964

Answers (1)

floriank
floriank

Reputation: 25698

Well, read the documentation for Model::exists().

Returns true if a record with particular ID exists.

If $id is not passed it calls Model::getID() to obtain the current record ID, and then performs a Model::find('count') on the currently configured datasource to ascertain the existence of the record in persistent storage.

It expects an id not a slug.

Here is a proper example from a model method to display an artist:

public function view($id = null, $options = array()) {
    $defaults = array(
        'contain' => array(
            /* ... */
        ),
        'conditions' => array(
            'OR' => array(
                $this->alias . '.' . $this->primaryKey => $id,
                $this->alias . '.slug' => $id
            )
        )
    );

    $artist = $this->find('first', Hash::merge($defaults, $options));

    if (empty($artist)) {
        throw new NotFoundException(__('Invalid Artist'));
    }

    return $artist;
}

The controllers try/catches the exception and sets the exception message to the session by calling Session->setFlasH(). Easy. :)

Upvotes: 3

Related Questions