Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Новини 04 листопада 2026

Laravel 13.40: довгі завдання черги, insertBefore() для middleware і strict для запиту

Laravel 13.40.0 вийшов 3 листопада. Головне в ньому - спостереження за фоновою роботою: фреймворк тепер сам повідомляє, коли завдання черги чи задача планувальника виконуються задовго, без сторонніх пакетів і власних слухачів. Поруч - зручніше налаштування вбудованого стеку middleware, строгий режим для читання даних запиту і продовження теми реплік, яку ми розбирали в огляді 13.36-13.38.

Завдання черги, що виконуються задовго

Для запитів до бази в Laravel давно є DB::whenQueryingForLongerThan(), для HTTP-запитів і команд - whenRequestLifecycleIsLongerThan() і whenCommandLifecycleIsLongerThan(). Для завдань черги аналога не було. Тепер він є (#62141):

use Carbon\CarbonInterval;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Queue;

// AppServiceProvider::boot()
Queue::whenJobRunsLongerThan(CarbonInterval::seconds(90), function ($job, $duration) {
    Log::warning("{$job->resolveName()} виконувалося {$duration} мс");
});

Метод слухає подію JobAttempted, яка після 13.39 несе тривалість кожної спроби в мілісекундах (про це ми писали в огляді 13.39). Тому колбек спрацьовує і для спроб, що впали з винятком, на відміну від Queue::after(), який бачить лише успішні. Автор PR пояснює сценарій просто: знати, яке завдання і скільки працювало, щоб вчасно перенести його на потужніший воркер або помітити, що воно підбирається до свого timeout чи ліміту хостингу.

Задачі планувальника, що виконуються задовго

Той самий автор додав парний метод для планувальника (#62233):

use Carbon\CarbonInterval;
use Illuminate\Console\Scheduling\Event;
use Illuminate\Support\Facades\Schedule;

Schedule::whenTaskRunsLongerThan(CarbonInterval::minutes(45), function (Event $task, float $runtime) {
    Log::warning("Задача [{$task->getSummaryForDisplay()}] виконувалася {$runtime} с");
});

Колбек отримує задачу і час виконання в секундах та спрацьовує як після успішного завершення (ScheduledTaskFinished), так і після невдачі (ScheduledTaskFailed).

Ще одна зміна для тих, хто запускає планувальник на кількох серверах: коли задачу з onOneServer() уже виконав інший сервер, тепер диспатчиться подія ScheduledTaskSkipped (#62256). Раніше був лише рядок «Skipping [...] because the command already ran on another server» у виводі, який на частині інфраструктури взагалі ніхто не бачить. Тепер пропуск можна порахувати в метриках і довести, що задача не загубилася.

Пастка з одиницями

Обидва методи приймають поріг як CarbonInterval, DateTimeInterface або число. І саме з числом легко помилитися: у черзі ціле число порівнюється з тривалістю в мілісекундах, а в планувальнику - з часом у секундах. Queue::whenJobRunsLongerThan(90, ...) спрацює вже на завданні довжиною в 90 мілісекунд, тобто майже на всіх. Передавайте CarbonInterval, і метод сам переведе його в потрібні одиниці.

Друге обмеження видно з коду schedule:run. Для задач з runInBackground() подія ScheduledTaskFinished надходить одразу після запуску фонового процесу, і в runtime потрапляє лише час на його старт. Тож довгу фонову задачу whenTaskRunsLongerThan() не помітить.

Власний middleware поруч із вбудованим

Щоб поставити свій middleware в глобальний стек саме після TrustProxies чи перед TrimStrings, раніше доводилося переоголошувати частину стеку за замовчуванням. У 13.40 $middleware->replace() приймає масив (#62230), а поверх цього з'явилися короткі методи (#62261):

use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings;
use Illuminate\Http\Middleware\TrustProxies;

->withMiddleware(function (Middleware $middleware) {
    // Після вбудованого TrustProxies
    $middleware->insertAfter(TrustProxies::class, StripCrossOriginReferer::class);

    // Перед вбудованим TrimStrings
    $middleware->insertBefore(TrimStrings::class, SanitiseStrings::class);

    // Замінити один middleware двома
    $middleware->replace(Foo::class, [Bar::class, Baz::class]);
})

Для груп є insertBeforeInGroup() і insertAfterInGroup() з назвою групи першим аргументом. Методи враховують уже зроблені заміни: якщо TrimStrings до того замінили на щось інше, нове вставиться поруч із заміною.

Строгий режим для даних запиту

$request->integer(), boolean(), string() і float() досі робили звичайне приведення типу. Звідси дві проблеми, які описав автор PR (#62254): ?name[]=chris змушує $request->string('name') кинути «Array to string conversion», а ?count=abc123 перетворюється на 0, і значення за замовчуванням так і не використовується. Новий третій аргумент strict повертає значення за замовчуванням, якщо дані не того типу:

// ?count=abc123
$request->integer('count', 5);               // 0
$request->integer('count', 5, strict: true); // 5

// ?name[]=chris
$request->string('name', '', strict: true);  // порожній Stringable замість винятку

Для boolean() строгий режим приймає лише 1, true, on, yes, 0, false, off і no. Методи живуть у трейті InteractsWithData, тож прапорець працює всюди, де він підключений. Валідацію це не замінює, але для логіки «якщо прийшло число, беремо його» тепер не потрібне окреме правило.

Репліки: чи дійшов запис

У 13.38 з'явився PreventStaleDatabaseReads, який після запису веде читання на write-сервер протягом заданого часу. Слабке місце - сам цей час: невідомо, чи вистачить секунди. Тобіас Петрі (Tobias Petry) додав основу, щоб не вгадувати, а знати (#62198):

// на primary
$user->orders()->create([...]);
$commitId = DB::getLastCommitId();

// на репліці
DB::hasCommitId($commitId);          // миттєва перевірка
DB::hasCommitId($commitId, wait: 2); // чекати до 2 секунд

Є ще DB::mergeCommitIds(), щоб об'єднати кілька ідентифікаторів в один і чекати на всі. Підтримуються MySQL (потрібні log_bin і gtid_mode = ON), MariaDB (потрібен log_bin) і PostgreSQL, де очікування з wait вимагає PostgreSQL 19. Інші драйвери кидають RuntimeException. Поки це саме будівельні блоки: PreventStaleDatabaseReads їх ще не використовує, хоча автор пише, що це наступний крок.

Що ще в релізі

queue:work тепер показує завдання, повернуті в чергу через WithoutOverlapping, RateLimited чи вручну, як RELEASED, а не DONE (#62180), так само, як це вже робив вивід --json. Решта - кілька десятків виправлень для SQL Server, PostgreSQL, SQLite, пагінації та Redis-кешу з тегами. Окремо - виправлення безпеки в драйвері process фасаду Concurrency (#62297), про яке ми напишемо окремо.

Чи варто оновлюватися

Так, і бажано не відкладати: хоча б через виправлення в Concurrency, якщо ви користуєтеся Concurrency::run(). Нові методи опційні й поведінку наявного коду не змінюють. Після оновлення має сенс додати в AppServiceProvider обидва пороги з CarbonInterval, підібравши їх під ваш timeout і найдовші задачі розкладу, а у місцях, де ви читаєте з запиту числа без валідації, увімкнути strict: true.

0

Читати в документації

Коментарі

Увійдіть, щоб залишити коментар

Будьте першим, хто залишить коментар!

Читайте також

Новини 04 листопада 2026

Вразливість у Concurrency: вивід задачі міг призвести до виконання коду в Laravel

Laravel 13.40.0 і 12.71.0 закривають вразливість у драйвері process фасаду Concurrency: задача, яка друкує текст від користувача, могла підробити свій результат, а батьківський процес робив його unserialize(). Пояснюємо, кого це стосується і що зробити до оновлення.

1
Новини 04 листопада 2026

Synapse 0.3: дашборд для агентів на Laravel AI SDK навчився схвалювати інструменти

Synapse від Redberry - відкритий dev-дашборд для агентів на Laravel AI SDK: знаходить агентів у застосунку, дає говорити з ними в браузері й показує виклики інструментів, токени та міркування. У 0.3 додано схвалення інструментів, джерела, пояснення зупинок і інспектор кроків, а 0.3.1 виправляє запис розмов під Octane.

1

Вакансії за темою

King Group Нова
Сьогодні

Middle PHP developer

Middle PHP розробник для високонавантаженої веб-платформи Social Casino/Online Casino: розвиток продукту, перехід монолітного проєкту на мікросервіси (Symfony), оптимізація баз даних, написання unit та functional тестів. Стек: PHP 7.4, Symfony 4, Yii, PostgreSQL 14, Redis, RabbitMQ, NGINX. Вимоги: 3-4+ роки продуктового досвіду з PHP, Yii, Symfony, PostgreSQL, розуміння REST API, Git, ООП та SOLID. Досвід з брокерами повідомлень і DDD буде плюсом.

Tech Lead — Fintech

Tech Lead для фінтех-платформи бізнес-витрат і платежів: активна розробка, архітектурні рішення, стабільність продакшену та менторство команди. Ключовий стек: PHP, Laravel/Lumen, MySQL, Redis, Docker, знання JavaScript (Vue.js, React на базовому рівні). Вимоги: розуміння життєвого циклу карткових транзакцій і криптовалют, досвід побудови надійних фінансових систем (баланси, звірка, аудит, безпечні API), DevOps-навички на Linux.

Bewort Нова
Сьогодні

Senior Full-Stack Developer (PHP/Laravel, Vue)

Розробка та розвиток ключових функцій корпоративної платформи на Laravel з обробкою бекенду та фронтенду на Vue. Потрібні глибокі знання внутрішньої архітектури фреймворку, досвід застосування SOLID, DDD, подій і черг, а також досвід роботи зі складними проєктами. Обов'язкове активне використання AI-інструментів для написання коду та англійська не нижче B2. Переваги: досвід із Vue, мультитенантними SaaS, AWS, CI/CD та LLM-інтеграціями.

Пакети за темою

Kalimera

welldigit/kalimera

Interactive installer that scaffolds Laravel applications the Well Digit way.

v1.0.0 16

Bagisto

bagisto/bagisto

Bagisto — це платформа для електронної комерції, побудована на Laravel. Вона надає готове рішення для створення та управління інтернет-магазинами з підтримкою каталогу товарів, замовлень, платежів та клієнтів.

28,325 v2.5.0 13 28