Laravel v13.6.0 представляє "debounceable" завдання у чергах: якщо одне й те саме завдання запускається кілька разів протягом певного часу, виконається лише останній виклик. Також у релізі з’явилася підтримка JSON-відповідей для вбудованого Health Route, новий JsonFormatter для логування, інтеграція з Cloudflare Email Service та низка внутрішніх оптимізацій.
- Debounce-завдання у чергах з атрибутом
#[DebounceFor] - JSON-відповіді для системного маршруту перевірки стану (
/up) - Новий JsonFormatter для структурованого логування у JSON
- Підтримка Cloudflare Email Service
- Підтримка масиву pivot-масивів для методу
hasAttached - Покращені Model Assertions для тестування
- Виправлення помилок та оптимізація продуктивності
# Що нового
# Debounceable Queued Jobs
Цей реліз додає підтримку debouncing для завдань у чергах. Коли одне й те саме завдання відправляється кілька разів за короткий проміжок часу, виконається лише останній запуск — попередні виклики будуть автоматично скасовані безпосередньо перед виконанням.
Використовуйте атрибут #[DebounceFor] для будь-якого завдання ShouldQueue:
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\Attributes\DebounceFor;
#[DebounceFor(30)]
class RebuildSearchIndex implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public function __construct(public int $documentId) {}
public function debounceId(): string
{
return (string) $this->documentId;
}
public function handle(): void
{
SearchIndex::rebuild($this->documentId);
}
}
// Користувач редагує документ 10 разів за 30 секунд — виконається лише останній запуск
RebuildSearchIndex::dispatch($document->id);
Debouncing також можна налаштувати безпосередньо під час виклику завдання, не змінюючи його клас:
dispatch(new SyncExternalData($accountId))->debounceFor(30);
Параметр maxWait дозволяє встановити максимальний час очікування, після якого завдання обов'язково виконається:
#[DebounceFor(30, maxWait: 120)]
class SyncDashboard implements ShouldQueue { ... }
На відміну від ShouldBeUnique, де нові виклики відхиляються ще на етапі відправлення, механізм debounce дозволяє останньому виклику "перемогти" вже в момент виконання.
Pull Request: #59507 від @matthewnessworthy
# JSON-відповіді для Health Route
Вбудований маршрут /up тепер повертає JSON, якщо запит очікує на такий формат. Раніше маршрут завжди віддавав HTML, що було незручно для API-застосунків, чиї балансувальники навантаження та моніторинги працюють із JSON.
Якщо $request->expectsJson() повертає true, маршрут /up віддасть:
{"status": "Application is up"}
Або у випадку проблем (коли спрацьовує лісенер DiagnosingHealth і вимкнено debug mode):
{"status": "Application experiencing problems"}
Коди статусів (200 / 500) залишилися без змін, а звичайні запити й надалі отримуватимуть стандартну Blade-сторінку.
Pull Request: #59710 від @WendellAdriel
# JsonFormatter
Новий JsonFormatter забезпечує структурований вивід логів у JSON. Це спрощує інтеграцію із системами агрегації на кшталт ELK stack або Datadog:
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Illuminate\Support\Facades\Log;
$handler = new StreamHandler('php://stdout');
$handler->setFormatter(new \Illuminate\Log\Formatters\JsonFormatter);
Log::build(['handler' => $handler])->info('User logged in', ['user_id' => 1]);
Pull Request: #59756 від @cosmastech
# Підтримка Cloudflare Email Service
Laravel тепер підтримує Cloudflare Email Service для розсилок через інфраструктуру Cloudflare. Налаштувати транспорт можна у config/services.php:
'cloudflare' => [
'account_id' => env('CLOUDFLARE_ACCOUNT_ID'),
'token' => env('CLOUDFLARE_TOKEN'),
],
Pull Request: #59735 від @dwightwatson
# Масив Pivot-масивів для hasAttached
Метод фабрики hasAttached тепер приймає масив із кількох pivot-масивів. Це полегшує створення моделей із різними значеннями у проміжних таблицях:
$user = User::factory()
->hasAttached(Role::factory()->count(2), [
['admin' => 'Y'],
['admin' => 'N'],
])
->create();
Pull Request: #59723 від @jackbayliss
# Покращені Model Assertions
Асерти для бази даних у тестах тепер підтримують масиви, що дозволяє перевіряти кілька записів одним викликом:
$this->assertDatabaseHas(User::class, [
['name' => 'Alice', 'email' => 'alice@example.com'],
['name' => 'Bob', 'email' => 'bob@example.com'],
]);
$this->assertDatabaseMissing(User::class, [
['name' => 'Charlie', 'email' => 'charlie@example.com'],
]);
Pull Request: #59752 від @jackbayliss
# Інші виправлення та покращення
Queue:
- Рядок
Queue::routeтепер за замовчуванням веде лише до черги (#59711) - Підтримка іменованих credential providers для SQS-з'єднань (#59733)
Validation:
- Виправлено правило
digits_betweenдля нерядкових значень (#59717) - Додано приведення до рядка перед
preg_matchу правилах decimal, max_digits та min_digits (#59739)
Підтримка Enum:
- Додано підтримку Enum у PasswordBrokerManager (#59714)
- Додано підтримку Enum у BroadcastManager (#59713)
- Додано підтримку Enum у NotificationChannelManager (#59783)
Інше:
Cursor::fromEncodedтепер повертає null при некоректних даних (#59699)- Валідація MAC тепер проводиться за всіма ключами дешифрування (#59742)
- Розширено використання generic TModel у класі Factory (#59780)
Посилання