Tengo una lista de campos de fecha y todos ellos tienen la misma lógica en sus mutadores. Me gustaría extraer esta funcionalidad a un rasgo para que en el futuro todo lo que necesite sea crear una matriz de campos de fecha en el modelo y usar el rasgo.
Algo como esto:
foreach( $dates as $date ) { $dateCamelCase = $this->dashesToUpperCase($date); $setDateFunctionName ='set'.$dateCamelCase.'Attribute'; $this->{$setDateFunctionName} = function() use($date) { $this->attributes[$date] = date( 'Ym-d', strtotime( $date )); }; }Antes de responder a su pregunta específica, primero veamos cómo funcionan los mutadores Eloquent.
Todas las clases derivadas de Eloquent Model tienen sus __set() y offsetSet() para llamar al método setAttribute que se encarga de establecer el valor del atributo y mutarlo, si es necesario.
Antes de establecer el valor, comprueba:
Al comprender esto, podemos simplemente aprovechar el proceso y sobrecargarlo con nuestra propia lógica personalizada. Aquí hay una implementación:
<?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('Ym-d', strtotime($value)); } // Handover the rest to Laravel's own setAttribute(), so that other // mutators will remain intact... return parent::setAttribute($key, $value); } }No hace falta decir que sus modelos requieren usar este rasgo para habilitar la funcionalidad.
Si la mutación de fechas es el único caso de uso que necesita para tener "mutadores con nombre dinámico" , eso no es necesario en absoluto. Como ya habrás notado , los campos de fecha de Eloquent pueden ser reformateados por el propio Laravel:
class Whatever extends Model { protected $dates = [ 'date_field_1', 'date_field_2', // ... ]; protected $dateFormat = 'Ym-d'; } Todos los campos enumerados allí tendrán el formato de $dateFormat . Entonces no reinventemos la rueda.