【问题标题】:Laravel 5 Eloquent, How to set cast attribute dynamicallyLaravel 5 Eloquent,如何动态设置强制转换属性
【发布时间】:2015-08-06 04:47:35
【问题描述】:

在 laravel 5.1 中有一个称为属性转换的新功能,在此处有详细记录: http://laravel.com/docs/5.1/eloquent-mutators#attribute-casting

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

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

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

可以设置value 属性转换,取决于type 字段,在写入(创建/更新)和获取中都有效?

【问题讨论】:

    标签: php laravel casting laravel-5 eloquent


    【解决方案1】:

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

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

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

    更新:

    当从数据库中读取数据时,上面的工作完美。写入数据时,必须确保 type 设置在 value 之前。有两种选择:

    1. 始终传递属性数组,其中 type 键位于 value 键之前 - 目前模型的 fill() 方法尊重处理数据时的键顺序,但它不是面向未来的。

    2. 在设置其他属性之前明确设置 type 属性。使用以下代码即可轻松完成:

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

    【讨论】:

    • 啊,我喜欢这样。比我的选择要好得多。该睡觉了。
    • 酷 :) 我还没有测试过这个确切的代码,所以如果您有任何问题,请告诉我,我会为您解决问题
    • 我可以在您的表格中看到类型列 - 我假设这用于确定演员表的类型,对吧?
    • 查看 Eloquent 模型的代码,除了确保在值之前设置类型之外别无他法——所有涉及转换的方法都只能访问当前正在转换的属性,而不是整个更改集.但是创建/更新在设置值时尊重 $attributes 数组中的顺序,以便您可以使用它。
    • 非常愉快的聊天@jedrzej.kurylo 你拯救了我的一天:D
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      这里的一些答案真的是想太多了,或者他们是微妙的错误。

      原理只是在需要之前设置 $casts 属性,例如。在向数据库写入或读取属性之前。

      在我的情况下,我需要使用配置的列名并进行转换。因为 PHP 不允许在常量表达式中调用函数,所以不能在类声明中设置,所以我只是在模型的构造函数中声明了我的列/属性的强制转换。

      <?php
      
      namespace App\Models;
      
      use Illuminate\Database\Eloquent\Model; 
      
      class MyModel extends Model
      {
          protected $casts = [
              // we can't call a function in a class constant expression or
              // we'll get 'Constant expression contains invalid operations'
              config('my-table.array-column.name') => 'array',
          ];
      
          public function __construct()
          {
              $this->casts = array_merge(
                  $this->casts,
                  [
                      // my column name is configured so it isn't known at
                      // compile-time so I have to set its cast run-time;
                      // the model's constructor is as good a place as any
                      config('my-table.array-column.name') => 'array',
                  ]
              );
      
              parent::__construct(...func_get_args());
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-29
        • 1970-01-01
        • 1970-01-01
        • 2016-11-12
        • 1970-01-01
        • 2013-09-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多