Laravel 13.26 представляє новий драйвер файлової системи read-through, що дозволяє нашаровувати основний диск на резервний та копіювати файли при першому читанні. Також у релізі: функція debounce для queued event listeners та метод Queue::forward() для перенаправлення черг без зміни класів завдань. Команда Laravel випустила версію 13.26.0 18 серпня 2026 року.
- Драйвер
read-throughдля файлової системи з опціональним режимом без копіювання. - Атрибут
#[DebounceFor]тепер підтримується для queued event listeners. Queue::forward()дозволяє перенаправляти завдання в іншу чергу або на інше connection.- Ітеровані пули процесів, спеціальний виняток для idle timeout та нові fake assertions для
Process. - Методи
orWhereKey(), підтримка замикань уwherePivot()та використання enums уinOrderOf(). - Подія
JobReleasedта сповіщення про призупинення черги у консолі worker. - Підтримка Guzzle 8 та серія виправлень для Redis cluster.
# Що нового
# Диски файлової системи Read-Through
Новий драйвер read-through об’єднує два диски в один. Система спочатку шукає файл на основному диску (primary), а якщо його там немає — звертається до резервного (fallback). Під час цього процесу файл автоматично копіюється на основний диск, що дозволяє поступово переносити лише затребувані дані. Операції запису, видалення та лістингу директорій виконуються лише на основному диску:
'assets' => [
'driver' => 'read-through',
'primary' => 'r2',
'fallback' => 'legacy-s3',
],
Диски можна вказувати за назвою або описувати конфігураційним масивом безпосередньо в налаштуваннях. Опція copy => false дозволяє віддавати файли з резервного сховища без копіювання — це зручно для розробки, коли локальне середовище звертається до продакшн-файлів. Помилки копіювання за замовчуванням ігноруються, щоб не переривати читання; активувати їх можна параметром throw_on_promotion_failure => true.
Функціонал реалізовано @taylorotwell, а опцію no-copy додав @jimbojsb.
# Debounced Queued Listeners
Атрибут #[DebounceFor], який з'явився для queued jobs у Laravel 13.6, тепер доступний і для queued event listeners. Якщо одна й та сама подія спрацьовує кілька разів поспіль, обробник виконається лише один раз — після останнього виклику у вказаному вікні часу:
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\Attributes\DebounceFor;
#[DebounceFor(30, maxWait: 120)]
class UpdateProductSearchIndex implements ShouldQueue
{
public function debounceId(ProductUpdated $event): string
{
return (string) $event->product->getKey();
}
public function handle(ProductUpdated $event): void
{
// Переіндексація виконається один раз з актуальним станом
}
}
Метод debounceId() обмежує дію затримки для конкретного ресурсу, а maxWait визначає максимальний час очікування, щоб постійний потік подій не відкладав роботу назавжди. Важливо: debounced listener не може одночасно реалізувати ShouldBeUnique, оскільки uniqueness зберігає перший виклик, а debouncing — останній.
Автор покращення — @stevebauman.
# Queue::forward()
Метод Queue::forward() дозволяє глобально перенаправляти всі завдання з однієї черги на іншу (або на інше з'єднання). Це налаштовується в одному місці (наприклад, у service provider) і не потребує змін у класах завдань чи місцях їх виклику:
use Illuminate\Support\Facades\Queue;
Queue::forward('reports', 'reports.fifo', 'cloud'); // Зміна назви та з'єднання
Queue::forward('payments', connection: 'cloud'); // Тільки зміна з'єднання
Queue::forward('updates', 'notifications'); // Тільки перейменування черги
Queue::forward([
'reports' => 'reports.fifo',
'emails' => 'emails.fifo',
], connection: 'cloud');
Перенаправлення працює через той самий хук, що і Queue::route(). Автор — @jackbayliss.
# Покращення роботи з Process
Фасад Process отримав три оновлення від @xurshudyan. Тепер пули процесів та їх результати підтримують ітерацію через foreach, оскільки класи реалізують IteratorAggregate.
Також впроваджено окремий виняток ProcessIdleTimedOutException. Раніше і загальний таймаут, і таймаут простою викликали один і той самий ProcessTimedOutException, хоча ці ситуації потребують різної реакції:
try {
Process::timeout(600)->idleTimeout(30)->run('./deploy.sh');
} catch (ProcessIdleTimedOutException $e) {
// Немає виводу протягом 30 секунд: зупиняємо та сповіщаємо
} catch (ProcessTimedOutException $e) {
// Процес працює, але занадто довго: даємо більше часу
}
Для тестування додано нові методи Process fake: assertRanCount() для перевірки кількості запущених процесів та assertRanInOrder() для перевірки послідовності команд.
# Нові можливості Eloquent Builder
Додано методи orWhereKey() та orWhereKeyNot(), що спрощують запити, де умова за первинним ключем має бути частиною гілки or.
Метод wherePivot() тепер приймає замикання з екземпляром builder, що дозволяє використовувати scope-методи безпосередньо на кастомних моделях зв'язку (pivot classes):
$project->subscribers()
->wherePivot(fn ($query) => $query->active()->notMuted())
->get();
Метод inOrderOf() тепер підтримує enums у списку значень:
$orders = Order::query()
->inOrderOf('status', [Status::Pending, Status::Processing, Status::Shipped])
->get();
# Прозорість роботи Queue Worker
Нова подія JobReleased спрацьовує, коли завдання повертається в чергу через власний обробник або middleware (наприклад, WithoutOverlapping). Раніше існувала лише подія JobReleasedAfterException, тому випуски завдань без помилок були "невидимими" для системи моніторингу.
Крім того, worker тепер виводить повідомлення, коли черга призупиняється або відновлює роботу. Це допомагає зрозуміти, чи worker завис, чи він просто очікує активації черги.
# Інші виправлення та покращення
- Додано підтримку Guzzle 8.
- Команда
db:seed --classтепер відображає прогрес виконання (RUNNING/DONE). - Покращено стабільність роботи з Redis cluster: виправлено перевірку призупинених черг, очищення тегів кешу та роботу коннекцій після збоїв у pipeline.
- У хмарному драйвері черг додано доступ до
managedQueues()та автоматичне повторення long-polls при таймаутах. - Виправлено логіку
throwUnless()та збереження порядку ключів уRequestпри об'єднанні файлів. - Усунено помилки у роботі з Microsoft SQL Server, Postgres JSON path та JSON:API параметрами.
- Оптимізовано реєстрацію команд
pailтаartisan dev.
Примітки щодо оновлення
Для більшості застосунків оновлення пройде непомітно. Зверніть увагу на два моменти: поєднання #[DebounceFor] та ShouldBeUnique тепер викликає LogicException, а внутрішня логіка whereKey() була консолідована, що може вплинути на вас лише у разі перевизначення цих методів у кастомному Eloquent builder.
Посилання
- Офіційний changelog
- Порівняння версій v13.25.0...v13.26.0
- PR: #61140 (read-through filesystem)
- PR: #61169 (debounced queued listeners)
- PR: #61188 (
Queue::forward())