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

Як масова дія Filament поводиться з тисячами записів і як не втратити політики й події моделей?

За замовчуванням масова дія завантажує всі вибрані моделі в пам'ять і передає Eloquent-колекцію в action(). Коли користувач натискає «вибрати все» на таблиці з 200 000 рядків, це легко перевищує ліміт пам'яті PHP.

Порційна обробка:

use Filament\Actions\BulkAction;
use Illuminate\Support\LazyCollection;

BulkAction::make('archive')
    ->chunkSelectedRecords(250)
    ->action(function (LazyCollection $records) {
        $records->each->update(['archived_at' => now()]);
    })

Записи підтягуються пачками, $records стає LazyCollection - пам'ять стала, а код майже не змінюється.

Без завантаження моделей взагалі:

use Illuminate\Support\Collection;

BulkAction::make('archive')
    ->fetchSelectedRecords(false)
    ->action(fn (Collection $records) => Order::whereKey($records)->update(['archived_at' => now()]))

Тут $records - лише ідентифікатори, а оновлення - один SQL-запит.

Ціна fetchSelectedRecords(false). Filament завантажує моделі не просто так:

  • щоб перевірити політику для кожного запису (authorizeIndividualRecords('update'));
  • щоб спрацювали події моделі (updating, deleted, спостерігачі, журнал активності, очищення кешу, Scout-індексація).

Масовий update()/delete() через запит обходить і те, і те. Для DeleteBulkAction це означає: без deleting-подій не видаляться файли, не оновиться пошуковий індекс, не запишеться аудит.

Як обирати:

Потреба Підхід
потрібні політики й події, записів сотні за замовчуванням
потрібні політики й події, записів тисячі chunkSelectedRecords()
чиста операція над даними, подій немає fetchSelectedRecords(false)
дуже довга операція поставити джобу в чергу з ідентифікаторами

Звіт про часткові невдачі. Якщо частина записів не обробилася, $action->reportBulkProcessingFailure() додасть причину в підсумкове сповіщення («3 з 50 замовлень не вдалося архівувати»), а authorizeIndividualRecords() так само повідомляє про записи, відкинуті політикою.

Довгі операції в HTTP-запиті ризикують тайм-аутом. Для них краще: дія ставить джобу (Bus::batch по пачках ідентифікаторів) і надсилає сповіщення в базу даних, коли все готово.

Докладніше в документації: Продуктивність масових дій

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання