2017-09-22 216 views
0

问题Laravel型号accessor和mutator通配符(*)

我想设置为一个模型属性,但与我具有属性存储名为tags_en不同的语言,tags_es,Tags_fr通配符 存取函数等。对于(8)语言标签

我想设置在Tag模型中的一个访问,一个突变基因的所有8种语言的子类型一次而不是使用夫妇访问/突变的方法为他们每个人。

通常人们会为他们每个人做以下事情,例如, 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模型类来做到这一点。这类似于验证器,你可以验证一个这样的数组中的每个元素:

$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构建者提供帮助吗?
+0

他们是否需要访问者和mutators?有没有一种方法,你不能只在模型上的方法? – tptcat

+0

我倾向于使用可用于模型的laravel框架方法,而不是重新发明轮子 - 当然,我认为可能有一种方法可以通过laravel Model类来实现。这与验证器类似,您可以验证数组中的每个元素,如下所示: $ validator = Validator :: make($ request-> all(),[ 'person。*。email'=>'email | unique :'users', 'person。*。first_name'=>'required_with:person。*。last_name', ]); – WillKoz

+0

我有点困惑:你是否真的将所有这些列作为你的数据库中的列:'tags_en','tags_es'等?或者你是否只有一个名为'tags'的JSON列? – tptcat

回答

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

这是一个有点不清楚我为你的数据库是如何建立,但是从我的理解,它与命名tags_entags_frtags_de列,表等

这里有一个想法:

  1. 添加保存要设置列的属性/得到
  2. $casts
  3. 创建一个自定义类型
  4. 重写boot()方法,并用它来设置tagson creatingupdating
  5. 覆盖的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个问题:如果你认为它应该被包括在内,那么最好的办法是一)通过GitHub的回购要求,甚至更好B)代码它起来并投入公关。堆栈溢出员工与Laravel无关,因此他们不能也不会做任何事情。