【问题标题】:Laravel Model Accessor and Mutator with wildcard (*)带有通配符 (*) 的 Laravel 模型访问器和修改器
【发布时间】:2017-09-22 03:14:52
【问题描述】:

问题

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

我想在标签模型中为所有 8 种语言子类型 一次 设置一个访问器和一个修改器,而不是使用一对访问器/修改器方法他们每个人。

通常会为每个人做以下事情,例如标签_zh

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 模型类使用通配符来实现。这类似于验证器,您可以像这样验证数组的每个元素:

$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 构建者请求改进(如果他们看到了)?

【问题讨论】:

  • 他们需要成为访问者和修改者吗?有没有理由不能只在模型上使用方法?
  • 我更愿意使用模型可用的 laravel 框架方法,而不是重新发明轮子——当然我认为可能有一种方法可以通过 laravel 模型类来实现。这类似于 Validator,您可以像这样验证数组的每个元素: $validator = Validator::make($request->all(), [ 'person.*.email' => 'email|unique:users' , 'person.*.first_name' => 'required_with:person.*.last_name', ]);
  • 我有点困惑:你的数据库中是否真的有所有这些列:tags_entags_es 等?还是您只有一个名为 tags 的 JSON 列?
  • 我在表格中有所有这些列,因为我需要在刀片中查看它们在不同的选项卡组下每个不同的语言。
  • 我认为我的解决方案对你有用。请看。

标签: php laravel wildcard accessor mutators


【解决方案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);
}

【讨论】:

    【解决方案2】:

    我有点不清楚您的数据库是如何设置的,但据我了解,它有一个包含名为tags_entags_frtags_de 等列的表。

    这是一个想法:

    1. 添加一个包含您要设置/获取的列的属性
    2. $casts 中创建自定义类型
    3. 覆盖boot()方法并使用它来设置creatingupdating的标签
    4. 覆盖castAttribute($key, $value) 方法并在您检索它时使用它将值转换回(这将像访问器一样工作)

    看起来像这样

    <?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 没有任何关系,所以他们不能也不会也不能做任何事情。

    【讨论】:

      【解决方案3】:

      有一个解决方案,Eloquent Mutators https://github.com/topclaudy/eloquent-mutators

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

      【讨论】:

        猜你喜欢
        • 2014-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-05
        • 2016-01-26
        • 1970-01-01
        • 2014-04-02
        相关资源
        最近更新 更多