Создание динамически названных мутаторов в моделях Laravel Eloquent
У меня есть список полей даты, и все они имеют одинаковую логику в своих мутаторах. Я хотел бы извлечь эту функциональность из признака, чтобы в будущем все, что мне было нужно, - это создать массив полей даты в модели и использовать признак.
Что-то вроде этого:
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 ));
};
}
1 ответ
Прежде чем ответить на ваш конкретный вопрос, давайте сначала посмотрим, как работают мутаторы Eloquent.
Как работают красноречивые мутаторы
Все красноречиво Model
классы имеют свои __set()
а также offsetSet()
методы для вызова setAttribute
метод, который заботится об установке значения атрибута и его изменении, если это необходимо.
Перед установкой значения он проверяет:
- Пользовательские методы мутатора
- Поля даты
- JSON Castables и поля
Нажав на процесс
Поняв это, мы можем просто подключиться к процессу и перегрузить его нашей собственной логикой. Вот реализация:
<?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
, Давайте не будем изобретать колесо тогда.