在 Laravel Eloquent 模型中创建动态命名的修改器

Creating dynamically named mutators in Laravel Eloquent models

我有一个日期字段列表,所有这些字段在它们的修改器中都有相同的逻辑。我想将此功能提取到一个特征中,以便将来我需要的只是在模型中创建一个日期字段数组并使用该特征。

像这样:

foreach( $dates as $date ) {
    $dateCamelCase = $this->dashesToUpperCase($date);
    $setDateFunctionName ='set'.$dateCamelCase.'Attribute';
    $this->{$setDateFunctionName} = function()  use($date) {
        $this->attributes[$date] = date( 'Y-m-d', strtotime( $date ));
    };
}

在回答您的具体问题之前,让我们先看看 Eloquent 增变器是如何工作的。

eloquent 突变器如何工作

所有 Eloquent Model-derived classes have their __set() and offsetSet() methods to call the setAttribute 方法负责设置属性值并在需要时改变它。

在设置值之前,它会检查:

  • 自定义修改器方法
  • 日期字段
  • JSON 浇注料和字段

进入流程

通过理解这一点,我们可以简单地利用流程并使用我们自己的自定义逻辑对其进行重载。这是一个实现:

<?php

namespace App\Models\Concerns;

use Illuminate\Database\Eloquent\Concerns\HasAttributes;

trait MutatesDatesOrWhatever
{
    public function setAttribute($key, $value)
    {
        // Custom mutation logic goes here before falling back to framework's 
        // implementation. 
        //
        // In your case, you need to check for date fields and mutate them 
        // as you wish. I assume you have put your date field names in the 
        // `$dates` model property and so we can utilize Laravel's own 
        // `isDateAttribute()` method here.
        //
        if ($value && $this->isDateAttribute($key)) {
            $value = date('Y-m-d', strtotime($value));
        }

        // Handover the rest to Laravel's own setAttribute(), so that other
        // mutators will remain intact...
        return parent::setAttribute($key, $value);
    }
}

不用说,您的模型需要使用此特征来启用该功能。

你不会需要它

如果 mutating dates is the only usecase you need to have "dynamically named mutators", that's not required at all. As you might have already noticed,Eloquent 的日期字段可以由 Laravel 本身重新格式化:

class Whatever extends Model 
{
    protected $dates = [
        'date_field_1', 
        'date_field_2', 
        // ...
    ];

    protected $dateFormat = 'Y-m-d';
}

此处列出的所有字段都将按照 $dateFormat 进行格式化。那就别再造轮子了