По дефолту в моделях Eloquent предполагается, что в таблице есть поля меток времени (timestamp) — created_at
и updated_at
. И с ними можно сделать много чего, настраивая их и выполняя интересные операций. Давайте посмотрим.
Если ваша таблица не имеет этих полей, и вы попытаетесь сделать что-то типа Model::create($arrayOfValues);
— вы получите SQL ошибку. Laravel попытается автоматически заполнить поля created_at
/updated_at
и не найдет их.
Чтобы отключить автоматические метки времени, в вашей модели необходимо добавить одно свойство:
class Role extends Model
{
public $timestamps = FALSE;
// ... другие свойства и методы модели
}
Что если вы работаете с базой данных, отличной от Laravel, и ваши поля меток времени имеют другие имена? Например, у вас есть create_time
и update_time
. К счастью, вы можете указать их и в модели:
class Role extends Model
{
const CREATED_AT = 'create_time';
const UPDATED_AT = 'update_time';
Здесь я просто процитирую официальную документацию Laravel:
По дефолту метки времени имеют формат 'Y-m-d H:i:s'
. Если вам нужен свой, то установите свойство $dateFormat
в вашей модели. Это свойство определяет, как даты хранятся в базе данных, а также их формат при сериализации модели в массив или JSON:
class Flight extends Model
{
/**
* Формат хранения поля даты модели
*
* @var string
*/
protected $dateFormat = 'U';
}
Исключением для автоматизации отметок времени является случай, когда вы создаете сводную таблицу в отношениях «многие ко многим», например, таблица 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();
}
Существует два «ярлыка» для сортировки данных по меткам времени.
Вместо:
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();
Каждый раз, когда вы обновляете запись Eloquent, она автоматически сохраняет текущую метку времени в поле updated_at
, и это крутая фишка.
Но иногда нужно избежать этого, например, вы увеличиваете какое-то значение и не хотите рассматривать это как «полное обновление записи».
Значит вам нужно сделать то же, что и выше — отключить метки времени, но только для этой операции:
$user = User::find(1);
$user->profile_views_count = 123;
$user->timestamps = false;
$user->save();
В противоположность последнему примеру — может быть, вы хотите установить новое значение ТОЛЬКО для поля 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');
}
}
Последний «бонусный» совет — скорее даже напоминание, потому что вы должны знать об этом.
По умолчанию, и created_at
и updated_at
преобразуются в $dates
модели Eloquent, поэтому вы можете выполнять над ними Carbon-операции без преобразования в экземпляр Carbon.
Например:
$user->created_at->addDays(3);
now()->diffInDays($user->updated_at);
Вот и все, короткие, но, надеюсь, полезные советы!