У Laravel 13.23 з'явився драйвер логування monthly, який створює окремий файл для кожного календарного місяця. Також оновлення додало підтримку тенентів (tenants) для SES v2, конструкцію USING для PostgreSQL при зміні типів стовпців та безпечне порівняння секретного ключа для обходу режиму обслуговування. Команда Laravel випустила версію 13.23.0 27 липня 2026 року.
- Новий драйвер
monthlyта відповідний канал логування. - Підтримка заголовка
X-SES-TENANT-NAMEу транспорті SES v2. - Метод
->using()у міграціях->change()для приведення типів у PostgreSQL. - Захищене від timing-атак порівняння секрету для bypass режиму обслуговування.
- Переписаний конвертер часових поясів у
schedule:listта інші виправлення.
# Що нового
# Драйвер логування Monthly
Драйвер daily ротує файли щодня, що зручно для систем із великою кількістю логів. Однак у невеликих застосунках це часто призводить до накопичення купи майже порожніх файлів. Новий драйвер monthly є золотою серединою між single та daily: він створює один файл на місяць (наприклад, laravel-2026-07.log):
'monthly' => [
'driver' => 'monthly',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'max_files' => 3,
'replace_placeholders' => true,
],
Обидва драйвери ротації тепер використовують спільний метод createRotatingDriver() у LogManager. Вони відрізняються лише форматом дати Monolog (FILE_PER_DAY проти FILE_PER_MONTH) та кількістю файлів, що зберігаються за замовчуванням: 14 для daily та 3 для monthly.
Також оновлено конфігурацію ліміту файлів. Канал daily тепер спершу шукає ключ max_files, а якщо його немає — використовує старий days. Це забезпечує зворотну сумісність. У стандартній конфігурації Laravel тепер використовується max_files для обох каналів.
# Підтримка тенентів у транспорті SES v2
Тененти в Amazon SES дозволяють ізолювати репутацію та налаштування відправки між різними групами користувачів. Раніше транспорт підтримував лише один глобальний тенент для всього застосунку. Тепер SES v2 зчитує заголовок X-SES-TENANT-NAME із повідомлення та передає його як параметр TenantName в SDK.
Вказати заголовок можна безпосередньо у mailable-класі:
use Illuminate\Mail\Mailables\Headers;
public function headers(): Headers
{
return new Headers(text: ['X-SES-TENANT-NAME' => 'tenant-id']);
}
Або у поштовому повідомленні сповіщення (notification):
return (new MailMessage)->withSymfonyMessage(function ($message) {
$message->getHeaders()->addTextHeader('X-SES-TENANT-NAME', 'tenant-id');
});
Якщо заголовок відсутній, відправка працює як раніше. На старих версіях AWS SDK, які не підтримують цю функцію, параметр просто ігнорується.
# Метод ->using() для змін у PostgreSQL
PostgreSQL не дозволяє змінювати тип стовпця на несумісний без явного приведення типів (наприклад, виникає помилка column "name" cannot be cast automatically to type date). Раніше у конструкторі схем Laravel не було можливості вказати таке приведення, тому міграції, що працювали в MySQL чи SQLite, часто не спрацьовували в PostgreSQL. Тепер для визначення стовпців доступний метод using():
Schema::table('currency_rates', function (Blueprint $table) {
$table->date('name')->using('name::date')->change();
});
Ця конструкція застосовується лише до PostgreSQL; інші бази даних її ігнорують.
# Безпечне порівняння секрету режиму обслуговування
Раніше механізм обходу режиму обслуговування порівнював секретний ключ двома способами: через hash_equals() при валідації та через звичайне === у middleware PreventRequestsDuringMaintenance. Тепер усюди використовується безпечне hash_equals() для запобігання timing-атакам. Крім того, перевірку isset() у middleware замінили на is_string(), щоб уникнути помилок TypeError при некоректних значеннях cookie.
Це зміна формату «defense-in-depth» (глибока оборона), а не виправлення критичної вразливості, оскільки підібрати ключ перебором байтів у такий спосіб практично неможливо. Для валідних даних поведінка системи залишається незмінною.
# Інші виправлення та покращення
- Повністю переписано конвертер часових поясів у
schedule:list. Тепер він коректно обробляє діапазони (8-23), кроки (*/2) та символи підстановки, враховуючи перехід на літній час та дробові зміщення (наприклад, UTC+5:45). - Помилки всередині логера депрекацій (deprecations) більше не призводять до фатального завершення роботи застосунку.
CookieJar::queued()тепер коректно повертає значення за замовчуванням, аArr::last()стабільно працює зnull.ImageManager::fromStorage()тепер приймає backed enum як назву диска.- Покращено типізацію для статичного аналізу в
Collection::select()та класіImage.
Посилання