Опубликовано:
Laravel: Ошибки связанные с мутабельностью Carbon
Типичная ошибка, которую вижу у разработчиков: использование
$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. Использовать CarbonImmutable
Laravel хелпер now()
или Carbon::now()
, по умолчанию, создают мутабельные объекты. Но вы можете специально создать объекты, которые не будут нести такое поведение:
$now = Carbon\CarbonImmutable::now();
$tomorrow = $now->addDays(1);
$twoDaysOrThreeDays = $now->addDays(2);