Select з методом relationship() сам завантажує варіанти зі зв'язку і зберігає вибір.
BelongsTo (один автор):
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
Select::make('author_id')
->relationship('author', 'name')
->searchable()
->preload()
->createOptionForm([
TextInput::make('name')->required(),
TextInput::make('email')->email()->required(),
])
->required();
searchable()- пошук по варіантах (за замовчуванням по колонці-назві;searchable(['name', 'email'])- по кількох);preload()- завантажити варіанти разом зі сторінкою, а не під час введення. Добре для десятків записів, погано для десятків тисяч;createOptionForm()- кнопка «+», модальне вікно створення нового автора, який одразу стає вибраним.
BelongsToMany (кілька тегів) - додати multiple():
Select::make('tags')
->multiple()
->relationship(titleAttribute: 'name')
->preload();
Filament сам синхронізує pivot-таблицю під час збереження форми.
Звуження варіантів:
Select::make('category_id')
->relationship('category', 'name', fn (Builder $query) => $query->where('is_active', true));
Що Filament перевіряє сам. Для Select автоматично діє правило «значення має бути серед дозволених варіантів». Підставити в запиті id запису, якого немає у варіантах (наприклад, неактивну категорію), не вийде.
Пастки:
- без
searchable()на великій таблиціSelectнамагається вивантажити всі записи у список; - для рекурсивних зв'язків (
parent_id) потрібенrelationship(..., ignoreRecord: true), щоб запис не можна було зробити батьком самого себе; - якщо поле
multiple()зі зв'язком треба зробитиdisabled(), викликатиdisabled()слід доrelationship()- інакше вимкнене поле все одно збереже зв'язок.