Creating dynamically named mutators in Laravel Eloquent models

I have a list of date fields and they all have the same logic in their mutators. I would like to highlight this functionality so that in the future I need to create an array of date fields in the model and use a trait.

Something like that:

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

      

+3


source to share


1 answer


Before answering your specific question, let's first take a look at how Ant Eacquent works.

How eloquent mutators work

Eloquent the All Model

- in all classes there __set()

and offsetSet()

methods to call setAttribute

, who will take care of setting the value of the attribute and its mutations, if necessary.

Before setting the value, it checks:

  • Custom mutator methods
  • Date fields
  • Spare materials and JSON fields

Process input

With this in mind, we can simply use the process and overload it with our own logic. Here's the implementation:



<?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 
        // 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 own 
        // `isDateAttribute()` method here.
        //
        if ($value && $this->isDateAttribute($key)) {
            $value = date('Y-m-d', strtotime($value));
        }

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

      

Needless to say, your models must use this trait to provide functionality.

You don't need it

If mutating dates are the only thing you need to have "dynamically named mutators" not required at all. As you might have noticed , the Bright Dates fields can be reformatted by Laravel itself:

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

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

      

All fields listed there will be formatted according to $dateFormat

. Then don't reinvent the wheel.

+1


source







All Articles