Команда Laravel випустила версію 13.17.0 з першокласною підтримкою метаданих маршрутів, інтеграцією з PostgreSQL transaction pooler, новою artisan-командою dev:list та обробником винятків Should Not Retry для роботи з чергами.
Підтримка метаданих маршрутів
Маршрути тепер можуть переносити структуровані метадані через весь конвеєр побудови маршрутів, включаючи серіалізацію route:cache та успадкування груп. Раніше розробники могли зберігати користувацькі дані всередині масиву action маршруту, але не існувало офіційного способу послідовного додавання структурованих даних через весь конвеєр. Цей реліз робить метадані першокласним атрибутом маршрутів.
Додайте метадані безпосередньо до маршруту за допомогою методу metadata():
Route::get('/users', [UserController::class, 'index'])
->metadata(['head' => ['title' => 'Users']]);
Зчитуйте їх з розв'язаного маршруту за допомогою getMetadata(), який підтримує dot-нотацію та необов'язкове значення за замовчуванням:
$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',
// ]
Також підтримуються resource та singleton маршрути. Використовуйте setMetadata() на екземплярі маршруту, щоб замінити метадані замість їх об'єднання.
Підтримка PostgreSQL Transaction Pooler
Цей реліз додає підтримку на рівні фреймворка для проксі-з'єднань PostgreSQL, які використовують transaction-mode pooling, включаючи PgBouncer, AWS RDS Proxy та Neon. У режимі transaction-mode pooling серверне з'єднання утримується лише протягом однієї транзакції, що робить підготовлені оператори несумісними з pooler. Laravel тепер обробляє це автоматично.
Увімкніть pooled режим у вашому конфігураційному файлі database.php:
'pgsql' => [
'driver' => 'pgsql',
'pooled' => true,
'url' => env('DATABASE_URL'),
// Опціонально: прямий (non-pooled) endpoint для DDL та міграцій
'direct' => env('DATABASE_DIRECT_URL'),
// ...
],
Коли pooled встановлено в true, з'єднання переключається на емульовані prepares, які сумісні з transaction-mode poolers. Команди, що потребують прямого з'єднання (міграції, schema:dump, db:wipe), автоматично направляються до direct endpoint. Інтерактивна команда php artisan db також за замовчуванням використовує direct endpoint, коли він налаштований.
З'єднання без pooled => true зберігають існуючу поведінку native-prepare, тому зміна повністю зворотно сумісна.
Команда dev:list
Нова команда php artisan dev:list виводить список усіх зареєстрованих dev-процесів разом із джерелом, яке зареєструвало кожен з них (ваш додаток або vendor-пакет). Це базується на команді artisan dev, доданій у версії 13.16.0.
php artisan dev:list
php artisan dev:list --except-vendor # приховати vendor-зареєстровані команди
php artisan dev:list --only-vendor # показати лише vendor-зареєстровані команди
php artisan dev:list --filter=reverb # фільтрувати за назвою
php artisan dev:list --json
Цей реліз також замінює блокувальник автоматичної реєстрації vendor з версії 13.16.0 на відстеження джерела. Кожна dev-команда тепер знає, чи вона була зареєстрована з вашого додатка або з vendor-пакета, що dev:list використовує для їх розрізнення у виводі.
Обробник винятків Should Not Retry
Завдання у чергах тепер можуть визначати на рівні винятку, чи слід повторювати спробу після помилки. Метод retry() може розміщуватися безпосередньо в класі винятку:
class PaymentGatewayException extends RuntimeException
{
public function retry(): bool
{
return false; // ніколи не повторювати цей виняток
}
}
Цей самий метод може бути зареєстрований через обробник withExceptions() у bootstrap вашого додатка для винятків, якими ви не володієте:
->withExceptions(function (Exceptions $exceptions) {
$exceptions->retry(PaymentGatewayException::class, function () {
return false;
});
})
Коли retry() повертає false, завдання негайно позначається як невдале без витрачання решти спроб.
Виправлення порядку викликів timezone для between()/unlessBetween()
Методи планувальника between() та unlessBetween() раніше оцінювали часовий пояс під час визначення, тому розміщення timezone() після них у ланцюжку мовчки використовувало неправильний часовий пояс:
// раніше: лише цей порядок працював правильно
$schedule->command('report')->timezone('Europe/Rome')->between('10:00', '12:00');
// раніше: це використовувало UTC замість Europe/Rome, мовчки
$schedule->command('report')->between('10:00', '12:00')->timezone('Europe/Rome');
Обидва ланцюжки тепер дають однаковий результат. Часовий пояс зчитується при виконанні фільтра, а не при його визначенні.
Прапорець --without-migration-data для schema:dump
Команда schema:dump приймає новий прапорець --without-migration-data, який пропускає рядки таблиці міграцій з виводу. Це корисно, коли потрібен чистий дамп схеми для налаштування тестів без відстеження виконаних міграцій:
php artisan schema:dump --without-migration-data
Інші виправлення та покращення
Версія 13.17.0 також включає:
- Зменшено кількість читань з кешу при debouncing завдань з
maxWait - з двох читань на відправку до одного
- Виправлено десеріалізацію кешу
FileStore для записів з короткими timestamps
- Виправлено перевірку vendor-реєстрації
DevCommands для коректного пропуску userland frames
- Очищено стан transaction manager при від'єднанні бази даних
- Дозволено
brick/math 0.18
- Покращено typehints у
InteractsWithData, boolean/numeric валідації та формах масивів
Повний список змін доступний у офіційному changelog та Release v13.17.0.