2017-09-22 280 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無關,因此他們不能也不會做任何事情。