I have multiple objects that I’d like to be accessible via human-readable URLs, so I am generating aliases (e.g. blog.com/this-is-an-alias/) for all database records.
What is the best practice for generating these automatically?
I’m currently hook the model’s ‘values()’ method and producing a new alias in there (based on the required ‘name’ field), but I can’t help but feel this could done more elegantly using, say, Kohana’s built-in filters.
Here’s the stripped-down model:
class Model_Category extends ORM {
// relevant rules:
public function rules(){
return array(
'alias' => array(
array('max_length', array(':value', 63)),
array(array($this, 'unique'), array(':field', ':value')),
),
'name' => array(
array('max_length', array(':value', 63)),
),
// (...)
);
}
// overrides default method:
public function values(array $values, array $expected = NULL){
if(!$this->_loaded){
if($values['name'] && !$values['alias'])
$values['alias'] = Helper_Form::to_alias($values['name']);
}
return parent::values($values, $expected);
}
}
FYI, the to_alias function simply looks like this:
return strtolower(substr(trim(preg_replace('/[^0-9a-zA-Z]+/','-',$str),'-'),0,63));
So, my questions:
- is it possible and/or advisable to access a model’s property–other than the one being filtered–from within a filter callback?
(so far my tests seem to suggest no, or, at best, unreliably) - more importantly, how can I build-in a uniqueness test? i.e., after auto-generating an alias, how can I be sure that slug isn’t already in use without throwing the model’s rules() exception?
I would do that automatic generation using filters as you mentioned. Below is my conception of doing this. For filter function you can pass some specific parameters like
:model,:value,:fieldand in this case I’d use:modelto get access to current model’s properties.Above example may be not fully functional but I hope you get the idea.