Laravel Model Accessor和Mutator with wildcard(*)

时间:2017-09-22 03:14:52

标签: php laravel wildcard accessor mutators

问题

我想为一个模型属性设置访问器和更改器,但是使用通配符 我有为不同语言存储的属性,名为tags_en,tags_es,Tags_fr等。(8)语言标签

我想在Tag模型中为所有8种语言子类型 一次 设置一个访问者和一个mutator,而不是使用几个accessor / mutator方法对于他们每个人。

通常人们会为每个人做以下事情,例如: tags_en

public function getTagsEnAttribute($tags){
    return join(', ', json_decode($tags));
}

public function setTagsEnAttribute($tags){
    $this->attributes['tags_en'] =
        json_encode(
            array_map('trim', explode(',', $tags))
        );
}

然后我必须为每种语言标记重复它们,这些标签目前只有8种不实用的语言。

我的目标

任何方式使用通配符做的访问器和变更器(当然这不起作用):

public function getTagsWildcardAttribute($tags){
    return join(', ', json_decode($tags));
}

类似的东西:

foreach ($tagsAttributes as $TagAttribute){
    //method building code for each tags language
}

类似的Laravel想法存在使用通配符验证

我假设可能有一种方法可以通过使用通配符的laravel Model类来实现。这类似于Validator,您可以在其中验证数组的每个元素:

$validator = Validator::make($request->all(), [ 
    'person.*.email' => 'email|unique:users', 
    'person.*.first_name' => 'required_with:person.*.last_name', 
]);

问题:

  1. 如果当前laravel框架中没有这些 访问者和带外卡 的变种人 - 你是否同意我的观点 在下一个laravel版本中添加
  2. 如果是这样,那么 如何正式询问laravel制造商在即将推出的版本中考虑这个问题
  3. Stackoverflow工作人员可以代表我们向laravel建设者询问改进情况(如果他们认为是这样)?

3 个答案:

答案 0 :(得分:1)

您可以扩展castAttribute()setAttribute()方法。

protected function castAttribute($key, $value) {
        if (is_null($value)) {
            return $value;
        }

        if ($this->isTagCastable($key)) {
            return join(', ', json_decode($value));
        }

        return parent::castAttribute($key, $value);
    }

public function setAttribute($key, $value)
{
    if ($this->isTagCastable($key)) {
        $this->attributes[$key] =
            json_encode(
                array_map('trim', explode(',', $value))
            );
    }

    return parent::setAttribute($key, $value);
}

protected function isTagCastable($key) {
    return preg_match('/tags_[a-z]{2}/', $key);
}

答案 1 :(得分:1)

关于数据库的设置方式,我有点不清楚,但根据我的理解,它有一个包含tags_entags_frtags_de等列的表格。

这是一个想法:

  1. 添加包含您要设置/获取的列的属性
  2. $casts
  3. 中创建自定义类型
  4. 覆盖boot()方法并使用它来设置creatingupdating
  5. 上的标签
  6. 覆盖castAttribute($key, $value)方法,并在检索时将其用于转换值(这将像访问者一样运行)
  7. 它看起来像这样

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class MyModel extends Model
    {
        protected static $tags = [
            'tags_en',
            'tags_fr',
            'tags_de',
        ];
    
        public static function boot()
        {
            static::creating(function ($model) {
                foreach (static::$tags as $tag) {
                    // You can customize exactly what you need to do here
                    $model->$tag = json_encode($model->tag);
                }
    
                unset($model->tag);
            });
    
            static::updating(function ($model) {
                foreach (static::$tags as $tag) {
                    // You can customize exactly what you need to do here
                    $model->$tag = json_encode($model->tag);
                }
    
                unset($model->tag);
            });
    
            parent::boot();
        }
    
        /**
         * Cast an attribute to a native PHP type.
         *
         * @param  string  $key
         * @param  mixed  $value
         * @return mixed
         */
        protected function castAttribute($key, $value)
        {
            if (in_array($key, static::$tags)) {
                return join(', ', (array) json_decode($value));
            }
    
            parent::castAttribute($key, $value);
        }
    }
    

    创建模型实例时:

    $t = App\MyModel::create([
        'name' => 'My Tags',
        'tag' => ['key' => 'value', 'key2' => 'value2']
    ]);
    

    然后当你检索一个实例时:

    $t = App\MyModel::find($id);
    echo $t->tags_en; // This will be handled by the `castAttribute($key, $value)` override
    

    关于你的最后3个问题:如果你认为它应该被包括在内,那么最好的办法是a)通过GitHub回复询问甚至更好b)编码并放入PR。 Stack Overflow工作人员与Laravel无关,因此他们不能也不会,也无法做任何事情。

答案 2 :(得分:0)

有一个解决方案,口才突变者 https://github.com/topclaudy/eloquent-mutators

安装软件包后,您将能够为Eloquent模型注册自定义访问器/更改器扩展。