KO3:使用ORM过滤器自动生成唯一的别名/ slug?

时间:2012-08-07 22:34:18

标签: php orm filter kohana unique

我有多个对象,我希望通过人类可读的URL访问,因此我为所有数据库记录生成别名(例如blog.com/this-is-an-alias/)。

自动生成这些内容的最佳做法是什么?

我目前正在勾选模型的'values()'方法并在那里生成一个新的别名(基于所需的'name'字段),但我不禁觉得这可以更优雅地使用,比如说,Kohana的内置过滤器。

这是精简模型:

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);
    }
}

仅供参考,to_alias函数看起来像这样:

return strtolower(substr(trim(preg_replace('/[^0-9a-zA-Z]+/','-',$str),'-'),0,63));

所以,我的问题:

  • 是否有可能和/或建议从过滤器回调中访问模型的属性(除了被过滤的属性)? (到目前为止,我的测试似乎表明没有,或者说,最好不可靠)
  • 更重要的是,如何构建唯一性测试?即,在自动生成别名之后,如何在不抛出模型规则的情况下确定slug尚未使用()例外?

1 个答案:

答案 0 :(得分:5)

我会像你提到的那样使用过滤器进行自动生成。以下是我这样做的概念。对于过滤功能,您可以传递一些特定参数,例如:model:value:field,在这种情况下我会使用:model来访问当前模型&#39 ; s属性。

class Model_Category extends ORM {

    public function filters()
    {
        return array(
            'slug' => array(
                array(array($this, 'create_slug'), array(':model')),
            ),
        );
    }

    public function create_slug($model)
    {
        $model = ($model instanceof ORM) ? $model : $this;

        $number = 1;

        $slug = UTF8::transliterate_to_ascii($model->name);
        $slug = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $slug);
        $slug = UTF8::strtolower(trim($slug, '-'));
        $slug = preg_replace("/[\/_|+ -]+/", '-', $slug);

        while ( ! $this->unique_slug($slug))
        {
            if ( ! preg_match('/\d+$/', $slug))
            {
                $slug .= '-'.$number;
            }
            $slug = preg_replace('/\d+$/', $number++, $slug);
        }

        return $slug;
    }

    public function unique_slug($slug)
    {
        return (bool) DB::select(array('COUNT("*")', 'total_count'))
            ->from($this->_table_name)
            ->where('slug', '=', $slug)
            ->where($this->_primary_key, '!=', $this->pk())
            ->execute($this->_db)
            ->get('total_count');
    }

}

以上示例可能不完全正常,但我希望您明白这一点。