Фільтри описують у ->filters([...]). Кожен фільтр отримує Eloquent-запит і звужує його.
Основні типи:
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Filters\TernaryFilter;
use Filament\Tables\Filters\TrashedFilter;
use Illuminate\Database\Eloquent\Builder;
->filters([
// чекбокс: увімкнено - діє query()
Filter::make('is_featured')
->label('Лише рекомендовані')
->query(fn (Builder $query): Builder => $query->where('is_featured', true)),
// список значень, можна кілька
SelectFilter::make('status')
->options([
'draft' => 'Чернетка',
'published' => 'Опубліковано',
])
->multiple(),
// за зв'язком, з пошуком
SelectFilter::make('author')
->relationship('author', 'name')
->searchable()
->preload(),
// три стани: так / ні / усі
TernaryFilter::make('email_verified_at')
->nullable(),
// для моделей з SoftDeletes
TrashedFilter::make(),
])
Власний фільтр - будь-які поля форми плюс query() з масивом $data, наприклад діапазон дат з двох DatePicker.
Чому фільтр не діє одразу. За замовчуванням зміни фільтрів відкладені: користувач вибирає кілька значень і тисне «Застосувати» - таблиця перезавантажується один раз. Це економить запити. Щоб фільтри працювали миттєво:
$table->deferFilters(false);
Корисне:
->persistFiltersInSession()- фільтри зберігаються між відвідуваннями сторінки;->default()на фільтрі - активний одразу;filtersLayout: FiltersLayout::AboveContent- показати фільтри над таблицею, а не в випадному меню.
Пастка: query() фільтра загортається в окрему групу where (...), щоб orWhere не зламав інші фільтри. Тому прибрати глобальний скоуп (наприклад, SoftDeletingScope) з query() не вийде - для цього є baseQuery().