Питання на співбесіді: Filament
Найпопулярніші питання з реальних Laravel/PHP співбесід для всіх рівнів
3 питання
Ресурс - це опис того, як модель виглядає в адмінці: таблиця, форма й сторінки навколо них.
php artisan make:filament-resource Vacancy --generate
Команда створює клас ресурсу, сторінки List/Create/Edit, а форму й таблицю виносить в окремі файли (Schemas/VacancyForm.php, Tables/VacancyTable.php). Прапорці --embed-schemas і --embed-table лишають їх усередині класу ресурсу.
Дві головні частини - форма й таблиця:
public static function form(Schema $schema): Schema
{
return $schema->components([
TextInput::make('title')
->required()
->maxLength(255),
Select::make('level')
->options(VacancyLevel::class)
->required(),
Toggle::make('is_published'),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('title')->searchable()->sortable(),
TextColumn::make('company.name')->label('Компанія'),
IconColumn::make('is_published')->boolean(),
])
->filters([
SelectFilter::make('level')->options(VacancyLevel::class),
]);
}
Що це дає без додаткового коду: список із пошуком, сортуванням і пагінацією, форми створення й редагування з валідацією, масові дії, фільтри.
На чому побудовано: Livewire відповідає за реактивність без написання JS, Alpine - за дрібні взаємодії в браузері, Tailwind - за оформлення. Тому Filament - це PHP-код, а не окремий фронтенд-застосунок.
Що варто знати одразу: форма й таблиця - це звичайні PHP-масиви обʼєктів, тож видимість поля, опції списку чи доступність дії задаються замиканнями й можуть залежати від користувача та стану запису.
Filament - фреймворк Server-Driven UI для Laravel: інтерфейси (адмінки, панелі) описуються на PHP через структуровані об'єкти, а не верстку.
public static function form(Schema $schema): Schema
{
return $schema->components([
TextInput::make('title')->required(),
Select::make('status')->options(Status::class),
]);
}
- Побудований на Livewire, Alpine.js і Tailwind CSS.
- Будівельні блоки: Resources, Forms, Tables, Actions, Infolists, Widgets.
- Компоненти ініціалізуються статичними
make()-методами; динамічні значення задаються замиканнями з утилітамиGet/Set.
Filament будує таблицю з Eloquent-запиту, тож усі звичайні проблеми продуктивності лишаються - але ховаються за декларативним синтаксисом.
N+1 у колонках. Колонка зі звʼязком робить запит на рядок:
TextColumn::make('company.name') // + 1 запит на кожен рядок
Лікується модифікацією запиту таблиці:
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()->with(['company', 'technologies']);
}
Лічильники. ->counts('vacancies') замість завантаження всієї колекції заради count().
Дорогі обчислення в state(). Замикання виконується для кожного рядка, тож звернення до бази всередині - те саме N+1, лише написане інакше.
Сортування й пошук за звʼязком роблять join, і без індексу на зовнішньому ключі це помітно:
TextColumn::make('company.name')
->searchable() // where по приєднаній таблиці
->sortable()
Що ще сповільнює адмінку:
->paginated([10, 25, 50, 'all'])з опцієюallна великій таблиці вивантажує все в памʼять одним кліком користувача.- Глобальний пошук по багатьох ресурсах виконує запит на кожен зареєстрований ресурс.
- Мініатюри без кешу:
ImageColumn, що генерує прев'ю на льоту, робить це для кожного рядка. - Опції
Selectбез->searchable()вивантажують усі записи довідника у форму.
Як шукати причину: Debugbar або Telescope на сторінці ресурсу покажуть кількість запитів. Таблиця на 25 рядків має вкладатися в одиниці запитів; десятки - ознака незавантаженого звʼязку.