I have a list of date fields, and all of them have the same logic in their mutators. I would like to extract this functionality to a trait so that in the future all I would need is to create an array of date fields in the model and use the trait.
Something like this:
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 ));
};
}
php - Creating dynamically named mutators in Laravel Eloquent models - Stack Overflow I have a list of date fields, and all of them have the same logic in their mutators. I would like to extract this functionality to a trait so that in the future all I would need is to create an arr...
Accessors, mutators, and attribute casting allow you to transform Eloquent attribute values when you retrieve or set them on model instances. For example, you may want to use the Laravel encrypter to encrypt a value while it is stored in the database, and then automatically decrypt the attribute when you access it on an Eloquent model.
* Interact with the user's first name. The mutator closure will receive the value that is being set on the attribute, allowing you to manipulate the value and return the manipulated value. To use our mutator, we only need to set the first_name attribute on an Eloquent model: In this example, the set callback will be called with the value Sally.
* Interact with the user's address. A mutator transforms an Eloquent attribute value when it is set. To define a mutator, you may provide the set argument when defining your attribute. Let's define a mutator for the first_name attribute.
Before answering your specific question, let's first see how Eloquent mutators work.
All Eloquent Model
-derived classes have their __set()
and offsetSet()
methods to call the setAttribute
method which takes care of setting the attribute value and mutating it, if needed.
Before setting the value, it checks for:
By understanding this, we can simply tap into the process and overload it with our own custom logic. Here's an 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'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);
}
}
Needless to say that your models require to use this trait to enable the functionality.
If 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's date 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 as per $dateFormat
. Let's not reinvent the wheel then.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With