在Laravel雄辩模型中创建动态命名的变异器

2022-05-25 00:00:00 php laravel laravel-5 traits mutators

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

类似以下内容:

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

解决方案

在回答您的具体问题之前,让我们先来看看能言善辩的变种是如何工作的。

能言善辩的变种人如何工作

所有雄辩的Model派生类都有它们的__set()offsetSet()方法来调用setAttribute方法,该方法负责设置属性值并在需要时更改属性值。

在设置值之前,它检查:

  • 自定义赋值方法
  • 日期字段
  • JSON浇注料和场地

进入流程

通过理解这一点,我们可以简单地进入流程并用我们自己的定制逻辑重载它。以下是一个实现:

<?php

namespace AppModelsConcerns;

use IlluminateDatabaseEloquentConcernsHasAttributes;

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是唯一需要";动态命名muters";的用例,则根本不需要。您可能已经noticed,eloquent的日期字段可以由Laravel本身重新格式化:

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

    protected $dateFormat = 'Y-m-d';
}
此处列出的所有字段都将按照$dateFormat进行格式化。那我们就不要重新发明轮子了。

相关文章