Laravel 5 Eloquent,如何动态设置强制转换属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31847050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 12:07:51  来源:igfitidea点击:

Laravel 5 Eloquent, How to set cast attribute dynamically

phplaravelcastinglaravel-5eloquent

提问by antoniputra

In laravel 5.1 there is new feature called Attribute Casting, well documented at here : http://laravel.com/docs/5.1/eloquent-mutators#attribute-casting

在 laravel 5.1 中有一个名为 Attribute Casting 的新功能,这里有详细记录:http: //laravel.com/docs/5.1/eloquent-mutators#attribute-casting

My question is, it is possible to make attribute casting dynamically ?

我的问题是,可以动态进行属性转换吗?

for example, I have a table with columns :

例如,我有一个带有列的表:

id | name          | value       | type    |
1  | Test_Array    | [somearray] | array   |
2  | Test_Boolean  | someboolean | boolean |

it is possible to set valueattribute cast, depends on typefield, that work both in write(create/update) and fetch ?

可以设置value属性转换,取决于type字段,在 write(create/update) 和 fetch 中都有效?

回答by jedrzej.kurylo

You'll need to overwrite Eloquent model's getCastType()method in your model class:

您需要在模型类中覆盖Eloquent模型的getCastType()方法:

protected function getCastType($key) {
  if ($key == 'value' && !empty($this->type)) {
    return $this->type;
  } else {
    return parent::getCastType($key);
  }
}

You'll also need to add valueto $this->castsso that Eloquent recognizes that field as castable. You can put the default cast there that will be used if you didn't set type.

您还需要为$this->casts添加,以便 Eloquent 将该字段识别为castable。如果您没有设置type,您可以将默认演员表放在那里。

Update:

更新:

The above works perfectly when reading data from the database. When writing data, you have to make sure that typeis set before value. There are 2 options:

从数据库读取数据时,上述方法完美无缺。写入数据时,您必须确保在value之前设置type。有2个选项:

  1. Always pass an array of attributes where typekey comes before valuekey - at the moment model's fill()method respects the order of keys when processing data, but it's not future-proof.

  2. Explicitely set typeattribute before setting other attributes. It can be easily done with the following code:

    $model == (new Model(['type' => $data['type']))->fill($data)->save();
    
  1. 始终传递类型键在键之前的属性数组- 目前模型的fill()方法在处理数据时尊重键的顺序,但它不是面向未来的。

  2. 在设置其他属性之前显式设置类型属性。可以使用以下代码轻松完成:

    $model == (new Model(['type' => $data['type']))->fill($data)->save();
    

回答by patricus

The $castsattribute it used whenever you access a field, not when it is fetched from the database. Therefore, you can update the $castsattribute after the model has been populated, and it should work fine whenever you access the valuefield. You just need to figure out how to update the $castsattribute when the typefield is changed.

$casts每次访问字段时使用的属性,而不是从数据库中获取时使用的属性。因此,您可以$casts在填充模型后更新属性,并且无论何时访问该value字段它都应该可以正常工作。您只需要弄清楚如何$caststype字段更改时更新属性。

One potential option would be to override the fill()method so that it calls the parent fill()method first, and then updates the $castsattribute with the data in the typefield.

一种可能的选择是覆盖该fill()方法,以便它首先调用父fill()方法,然后$casts使用type字段中的数据更新属性。

Another potential option would be to abuse the mutator functionality, and create a mutator on the typefield, so that whenever it changes, it would update the $castsattribute.

另一个可能的选择是滥用 mutator 功能,并在type字段上创建一个 mutator ,以便每当它发生变化时,它都会更新$casts属性。