Команда Laravel представила версію 13.17.0. Серед головних нововведень: повноцінна підтримка метаданих маршрутів, інтеграція з пулерами транзакцій Postgres, нова Artisan-команда dev:list та обробник виключень Should Not Retry для задач у черзі.
- Метадані маршрутів із підтримкою крапкової нотації та каскадним успадкуванням.
- Підтримка пулерів транзакцій Postgres (PgBouncer, RDS Proxy, Neon).
- Нова команда
dev:listдля перегляду зареєстрованих dev-процесів. - Обробник Should Not Retry для скасування повторних спроб виконання задач у черзі.
- Виправлення порядку виклику часових поясів у методах
between()таunlessBetween(). - Прапор
--without-migration-dataдля командиschema:dump. - Зменшення кількості звернень до кешу при використанні
maxWaitу debouncing.
# Що нового
# Підтримка метаданих маршрутів
Тепер маршрути можуть містити структуровані метадані протягом усього життєвого циклу — включно із серіалізацією через route:cache та успадкуванням у групах. Раніше розробники зберігали кастомні дані в масиві дій маршруту, але офіційного способу для зручної передачі структурованих даних не було. У цьому релізі метадані стали повноцінним атрибутом маршрутів.
Додати метадані можна безпосередньо через метод metadata():
Route::get('/users', [UserController::class, 'index'])
->metadata(['head' => ['title' => 'Users']]);
Зчитати їх можна за допомогою getMetadata(), який підтримує крапкову нотацію та значення за замовчуванням:
$request->route()->getMetadata('head.title'); // 'Users'
$request->route()->getMetadata('head.author', 'Taylor');
Метадані, задані для групи, поширюються на всі маршрути всередині. Асоціативні масиви об'єднуються рекурсивно, тоді як списки та скалярні значення замінюють успадковані:
Route::metadata(['head' => ['robots' => ['noindex'], 'author' => 'Taylor']])
->group(function () {
Route::get('/users', [UserController::class, 'index'])
->metadata(['head' => ['title' => 'Users']]);
});
// getMetadata('head') => [
// 'robots' => ['noindex'],
// 'author' => 'Taylor',
// 'title' => 'Users',
// ]
Також підтримуються маршрути ресурсів та синглтонів. Для повної заміни метаданих замість об'єднання використовуйте setMetadata(). Детальніше у #60530.
# Підтримка пулерів транзакцій Postgres
Реліз додає нативну підтримку проксі-з’єднань PostgreSQL, що використовують пул транзакцій (PgBouncer, AWS RDS Proxy, Neon). У такому режимі з’єднання з сервером утримується лише на час транзакції, що робило підготовлені вирази (prepared statements) несумісними з пулером. Laravel тепер обробляє це автоматично.
Увімкнути цей режим можна у конфігурації database.php:
'pgsql' => [
'driver' => 'pgsql',
'pooled' => true,
'url' => env('DATABASE_URL'),
// Опційно: пряме з’єднання для DDL та міграцій
'direct' => env('DATABASE_DIRECT_URL'),
// ...
],
Якщо параметр pooled має значення true, з’єднання перемикається на емуляцію підготовлених виразів. Команди, що потребують прямого доступу (міграції, schema:dump, db:wipe), автоматично використовують ендпоінт direct. Інтерактивна команда php artisan db за наявності конфігурації також за замовчуванням використовує пряме з’єднання.
Зміни повністю зворотно сумісні. Детальніше у #60425.
# Команда dev:list
Нова команда php artisan dev:list відображає всі зареєстровані dev-процеси та джерело їхнього походження (ваш додаток або сторонній пакет). Це розширення функціоналу artisan dev, представленого у версії 13.16.0.
php artisan dev:list
php artisan dev:list --except-vendor # приховати команди пакетів
php artisan dev:list --only-vendor # показати лише команди пакетів
php artisan dev:list --filter=reverb # фільтрація за назвою
php artisan dev:list --json
Кожна команда тепер відстежує своє джерело реєстрації, що дозволяє dev:list ефективно їх розділяти. Детальніше у #60573.
# Обробник виключень Should Not Retry
Тепер задачі в черзі можуть визначати на рівні виключення, чи потрібно повторювати спробу після помилки. Метод retry() можна реалізувати безпосередньо в класі виключення:
class PaymentGatewayException extends RuntimeException
{
public function retry(): bool
{
return false; // ніколи не повторювати при цьому виключенні
}
}
Для сторонніх виключень цей метод можна зареєструвати через обробник withExceptions() у завантажувачі додатка:
->withExceptions(function (Exceptions $exceptions) {
$exceptions->retry(PaymentGatewayException::class, function () {
return false;
});
})
Якщо retry() повертає false, задача миттєво позначається як провалена. Детальніше у #60552.
# Виправлення часових поясів у between() / unlessBetween()
Раніше методи планувальника between() та unlessBetween() обчислювали часовий пояс у момент визначення. Через це виклик timezone() після них у ланцюжку міг ігноруватися, використовуючи UTC за замовчуванням.
// Раніше: працював лише такий порядок
$schedule->command('report')->timezone('Europe/Rome')->between('10:00', '12:00');
// Раніше: цей варіант помилково використовував UTC
$schedule->command('report')->between('10:00', '12:00')->timezone('Europe/Rome');
Тепер обидва варіанти працюють коректно, оскільки часовий пояс зчитується безпосередньо під час перевірки фільтра. Детальніше у #60518.
# Прапор --without-migration-data для schema:dump
Команда schema:dump отримала прапор --without-migration-data, який дозволяє не включати дані про виконані міграції у фінальний SQL-файл. Це корисно для створення чистого дампу схеми для тестів.
php artisan schema:dump --without-migration-data
Детальніше у #60570.
# Інші виправлення та покращення
- Оптимізовано роботу з кешем при дебаунсингу задач із
maxWait: кількість запитів скорочено вдвічі (#60559). - Виправлено десеріалізацію кешу у
FileStoreдля записів із короткими мітками часу (#60543). - Виправлено перевірку реєстрації пакетів у
DevCommands(#60538). - Додано очищення стану менеджера транзакцій при розриві з'єднання з БД (#60574).
- Додано підтримку
brick/mathверсії 0.18 (#60560). - Покращено типізацію в
InteractsWithDataта валідацію числових/логічних значень (#60536, #60549, #60553).
Посилання