8 трюков с метками времени

Timestamps в Laravel

По дефолту в моделях Eloquent предполагается, что в таблице есть поля меток времени (timestamp) — created_at и updated_at. И с ними можно сделать много чего, настраивая их и выполняя интересные операций. Давайте посмотрим.

1. Отключение меток времени

Если ваша таблица не имеет этих полей, и вы попытаетесь сделать что-то типа Model::create($arrayOfValues); — вы получите SQL ошибку. Laravel попытается автоматически заполнить поля created_at/updated_at и не найдет их.

Чтобы отключить автоматические метки времени, в вашей модели необходимо добавить одно свойство:

class Role extends Model
{
    public $timestamps = FALSE;

    // ... другие свойства и методы модели
}

2. Изменение названия полей меток времени

Что если вы работаете с базой данных, отличной от Laravel, и ваши поля меток времени имеют другие имена? Например, у вас есть create_time и update_time. К счастью, вы можете указать их и в модели:

class Role extends Model
{
    const CREATED_AT = 'create_time';
    const UPDATED_AT = 'update_time'; 

3. Изменить формат меток времени

Здесь я просто процитирую официальную документацию Laravel:

По дефолту метки времени имеют формат 'Y-m-d H:i:s'. Если вам нужен свой, то установите свойство $dateFormat в вашей модели. Это свойство определяет, как даты хранятся в базе данных, а также их формат при сериализации модели в массив или JSON:

class Flight extends Model
{
    /**
     * Формат хранения поля даты модели
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

4. Многие ко многим: сводная таблица с метками времени

Исключением для автоматизации отметок времени является случай, когда вы создаете сводную таблицу в отношениях «многие ко многим», например, таблица role_user между таблицами пользователей и ролями.

В модели вы определяете отношения следующим образом:

class User extends Model
{
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}

И затем, когда нужно добавить роль пользователю, вы должны сделать что-то вроде этого:

$roleID = 1;
$user->roles()->attach($roleID);

По умолчанию сводные таблицы не содержат меток времени. И, в этом случае, Laravel не пытается заполнить поля created_at/updated_at.

Но если вы хотите сохранять автоматически метки времени, то вам нужно добавить их в файл миграции, а затем определить отношения, используя ->withTimestamps();

public function roles()
{
    return $this->belongsToMany(Role::class)->withTimestamps();
}

5. Сортировка меток времени через latest() и oldest()

Существует два «ярлыка» для сортировки данных по меткам времени.

Вместо:

User::orderBy('created_at', 'desc')->get();

Можно сделать быстрее:

User::latest()->get();

По умолчанию функция latest() будет сортировать по полю created_at.

Существует противоположный метод oldest(), который сортирует created_at по возрастанию.

User::oldest()->get();

Также вы можете указать другой столбец для сортировки. Например, если вы хотите использовать updated_at, то можно сделать так:

$lastUpdatedUser = User::newest('updated_at')->first();

6. Обновление без updated_at

Каждый раз, когда вы обновляете запись Eloquent, она автоматически сохраняет текущую метку времени в поле updated_at, и это крутая фишка.

Но иногда нужно избежать этого, например, вы увеличиваете какое-то значение и не хотите рассматривать это как «полное обновление записи».

Значит вам нужно сделать то же, что и выше — отключить метки времени, но только для этой операции:

$user = User::find(1);
$user->profile_views_count = 123;
$user->timestamps = false;
$user->save();

7. Привязка и Родительская привязка

В противоположность последнему примеру — может быть, вы хотите установить новое значение ТОЛЬКО для поля updated_at, не меняя другие.

Итак, вместо:

$user->update(['updated_at' => now()]);

Вы можете использовать более короткий метод:

$user->touch();

Другой случай — иногда нужно обновить не только updated_at текущей модели Eloquent, но и родительскую запись в отношениях.

Например, если какой-либо comment был обновлен, то вы должны учитывать, что у post тоже нужно обновить updated_at.

Значит нужно определить «родительскую привязку» моделей в модели Eloquent:

class Comment extends Model {

    protected $touches = ['post'];

    public function post()
    {
        return $this->belongsTo('Post');
    }

}

8. Поля меток времени автоматически Carbon’изированы

Последний «бонусный» совет — скорее даже напоминание, потому что вы должны знать об этом.

По умолчанию, и created_at и updated_at преобразуются в $dates модели Eloquent, поэтому вы можете выполнять над ними Carbon-операции без преобразования в экземпляр Carbon.

Например:

$user->created_at->addDays(3);
now()->diffInDays($user->updated_at);

Вот и все, короткие, но, надеюсь, полезные советы!

Автор: Povilas Korop
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.