Laravel: Ошибки связанные с мутабельностью Carbon

Источник: «Mutable Carbon Dates Errors: Use copy() or CarbonImmutable»
Типичная ошибка, которую вижу у разработчиков: использование $date->addDays(1), а затем ещё одного $date->addYears(1) в том же запросе и получение неправильных результатов. Позвольте мне объяснить.

Если выполнить несколько операций модификации с типичным объектом Carbon, они изменят исходный объект.

$now = now();
// Результат: 2023-01-17 09:08:49

$tomorrow = $now->addDays(1);
// Результат: 2023-01-18 09:08:49

$twoDaysOrThreeDays = $now->addDays(2);
// Результат: 2023-01-20 09:08:49

Как видите, начальная переменная — 17 января, а $now->addDays(2) добавляет два дня не к исходной переменной, а к переменной $tomorrow.

Другими словами, вот что происходит под капотом:

$now = $tomorrow = $now->addDays(1);

Итак, если вы хотите выполнить несколько операций с одним и тем же объектом Carbon в одном запросе, имейте в виду такое поведение и возможные ошибки.

Какие у вас варианты, чтобы переопределить его?

Вариант 1. Использовать copy()

Вы можете создать временный объект $now специально для этой операции, используя метод copy().

$tomorrow = $now->copy()->addDays(1);
$twoDaysOrThreeDays = $now->copy()->addDays(2);

// Значение $now останется тем же

Вариант 2. Использовать Carbon­Immutable

Laravel хелпер now() или Carbon::now(), по умолчанию, создают мутабельные объекты. Но вы можете специально создать объекты, которые не будут нести такое поведение:

$now = Carbon\CarbonImmutable::now();

$tomorrow = $now->addDays(1);
$twoDaysOrThreeDays = $now->addDays(2);

Дополнительные материалы

Предыдущая Статья

Laravel: Как тестировать invokable правила

Следующая Статья

Laravel API: Переопределе­ние Сообщения об Ошибке 404