Как создать универсальный геттер / мутатор для datetime в Laravel?
Я создал один, и я подумал, что это работает:
<?php
namespace App\Traits;
use Carbon\Carbon;
trait FormatDates
{
public function setAttribute($key, $value)
{
parent::setAttribute($key, $value);
if (strtotime($value))
$this->attributes[$key] = Carbon::parse($value);
}
}
Но есть проблема при вызове связанных моделей. Например, если у вас есть модель Article и Tag, и вы хотите получить все теги, подобные этому:
$article->tags
это возвращается null
из-за этого мутатора-геттера.
Как это исправить?
обновление 17.11.2017
Я нашел решение своей проблемы. Лучший способ представить дату в локали - использовать эту функцию:
\Carbon\Carbon::setToStringFormat("d.m.Y H:i");
просто создайте поставщика услуг или промежуточное программное обеспечение, и оно покажет все $ даты в нужном вам формате. Нет необходимости делать геттер.
2 ответа
Исходя из этого: https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Concerns/HasAttributes.html
В описании сказано:
Получить простой атрибут (не отношения).
К счастью, под ним есть еще два метода, называемые getRelationValue и getRelationshipFromMethod, и он читает:
Получить отношения.
Получить значение отношения из метода.
соответственно.
И в вашем примере, похоже, вы называете отношение.
Я думаю, что вы должны учитывать это при выполнении вашего универсального геттера / мутатора.
ОБНОВИТЬ:
Если вы проверяете код, getAttribute
также называет getRelationValue
метод. Но это последнее средство функции; если ключ не является ни атрибутом, ни мутатором, ни методом класса.
Вот заглушка: https://github.com/laravel/framework/blob/5.5/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
/**
* Get an attribute from the model.
*
* @param string $key
* @return mixed
*/
public function getAttribute($key)
{
if (! $key) {
return;
}
// If the attribute exists in the attribute array or has a "get" mutator we will
// get the attribute's value. Otherwise, we will proceed as if the developers
// are asking for a relationship's value. This covers both types of values.
if (array_key_exists($key, $this->attributes) ||
$this->hasGetMutator($key)) {
return $this->getAttributeValue($key);
}
// Here we will determine if the model base class itself contains this given key
// since we don't want to treat any of those methods as relationships because
// they are all intended as helper methods and none of these are relations.
if (method_exists(self::class, $key)) {
return;
}
return $this->getRelationValue($key);
}
ДРУГОЕ ОБНОВЛЕНИЕ
Поскольку вы изменили свой вопрос:
Вы можете просто поставить имя атрибута $casts
или же $dates
массив (в вашей модели), поэтому Laravel автоматически преобразует его в Carbon
экземпляр при доступе к нему, вот так:
class Article extends Model {
...
protected $dates = ['some_date_attribute`];
или с $casts
...
protected $casts = ['some_date_attributes' => 'date'];
Вы действительно можете избежать этого, это уже там!
На модели класса вы можете сделать:
protected $dates = ['nameOfTheDateOrTimestampTypeField','nameOfAnotherOne'];