【问题标题】:KO3: Automatically generate unique alias/slug using ORM filters?KO3:使用 ORM 过滤器自动生成唯一的别名/slug?
【发布时间】:2012-08-07 22:34:17
【问题描述】:

我希望通过人类可读的 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 尚未使用而不抛出模型的规则() 异常?

【问题讨论】:

    标签: php orm filter kohana unique


    【解决方案1】:

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

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

    以上示例可能功能不全,但我希望您能理解。

    【讨论】:

      猜你喜欢
      • 2015-12-19
      • 2010-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-25
      • 2015-06-26
      • 1970-01-01
      • 2022-12-16
      相关资源
      最近更新 更多