У меня есть список полей даты, и все они имеют одинаковую логику в своих мутаторах. Я хотел бы извлечь эту функциональность из признака, чтобы в будущем все, что мне было нужно, — это создать массив полей даты в модели и использовать признак.
Что-то вроде этого:
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.
Все красноречиво Model
-производные классы имеют свои __set()
а также offsetSet()
методы для вызова setAttribute
метод, который заботится об установке значения атрибута и его изменении, если это необходимо.
Перед установкой значения он проверяет:
Поняв это, мы можем просто подключиться к процессу и перегрузить его нашей собственной логикой. Вот реализация:
<?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);
}
}
Само собой разумеется, что ваши модели требуют использовать эту черту, чтобы включить функциональность.
Если мутирующие даты это единственный случай, когда вам нужно «Динамически названные мутаторы», это совсем не обязательно. Как вы уже могли заметил, Поля даты Eloquent могут быть переформатированы самим Laravel:
class Whatever extends Model
{
protected $dates = [
'date_field_1',
'date_field_2',
// ...
];
protected $dateFormat = 'Y-m-d';
}
Все перечисленные поля будут отформатированы в соответствии с $dateFormat
, Давайте не будем изобретать колесо тогда.
Других решений пока нет …