Створення записів · Filament
Зміна даних перед збереженням
Іноді потрібно змінити дані форми, перш ніж вони остаточно потраплять у базу. Для цього визначте метод mutateFormDataBeforeCreate() у класі сторінки Create: він приймає $data масивом і повертає змінену версію:
protected function mutateFormDataBeforeCreate(array $data): array
{
$data['user_id'] = auth()->id();
return $data;
}
Якщо ж ви створюєте записи в модальній дії, дивіться документацію по діях.
Налаштування процесу створення
Змінити те, як саме створюється запис, можна методом handleRecordCreation() у класі сторінки Create:
use Illuminate\Database\Eloquent\Model;
protected function handleRecordCreation(array $data): Model
{
return static::getModel()::create($data);
}
Якщо ж ви створюєте записи в модальній дії, дивіться документацію по діях.
Налаштування перенаправлень
Типово після збереження форми користувача буде перенаправлено на сторінку Edit ресурсу або на сторінку View, якщо вона є.
Задати власне перенаправлення після збереження форми можна, перевизначивши метод getRedirectUrl() у класі сторінки Create.
Наприклад, форма може перенаправляти назад на сторінку List:
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
Якщо ви хочете повертатися на попередню сторінку, а за її відсутності - на індексну:
protected function getRedirectUrl(): string
{
return $this->previousUrl ?? $this->getResource()::getUrl('index');
}
Також можна скористатися конфігурацією, щоб налаштувати типову сторінку перенаправлення одразу для всіх ресурсів:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->resourceCreatePageRedirect('index') // або
->resourceCreatePageRedirect('view') // або
->resourceCreatePageRedirect('edit');
}
Налаштування сповіщення про збереження
Коли запис успішно створено, користувачеві надсилається сповіщення, яке показує, що дія вдалася.
Щоб змінити заголовок цього сповіщення, визначте метод getCreatedNotificationTitle() у класі сторінки create:
protected function getCreatedNotificationTitle(): ?string
{
return 'User registered';
}
Якщо ж ви створюєте записи в модальній дії, дивіться документацію по діях.
Усе сповіщення цілком можна налаштувати, перевизначивши метод getCreatedNotification() у класі сторінки create:
use Filament\Notifications\Notification;
protected function getCreatedNotification(): ?Notification
{
return Notification::make()
->success()
->title('User registered')
->body('The user has been created successfully.');
}
Щоб повністю вимкнути сповіщення, поверніть null з методу getCreatedNotification() у класі сторінки create:
use Filament\Notifications\Notification;
protected function getCreatedNotification(): ?Notification
{
return null;
}
Створення ще одного запису
Вимкнення «створити ще один»
Щоб вимкнути можливість «create and create another», визначте властивість $canCreateAnother зі значенням false у класі сторінки Create:
protected static bool $canCreateAnother = false;
Якщо ж вам потрібна динамічна умова, за якої ця можливість вимикається, перевизначте метод canCreateAnother() у класі сторінки Create:
public function canCreateAnother(): bool
{
return false;
}
Збереження даних під час створення ще одного запису
Типово, коли користувач користується можливістю «create and create another», усі дані форми очищуються, щоб можна було почати з чистого аркуша. Якщо ви хочете зберегти частину даних форми, перевизначте метод preserveFormDataWhenCreatingAnother() у класі сторінки Create і поверніть ту частину масиву $data, яку слід залишити:
use Illuminate\Support\Arr;
protected function preserveFormDataWhenCreatingAnother(array $data): array
{
return Arr::only($data, ['is_admin', 'organization']);
}
Щоб зберегти всі дані, поверніть увесь масив $data:
protected function preserveFormDataWhenCreatingAnother(array $data): array
{
return $data;
}
Хуки життєвого циклу
Хуки дозволяють виконувати код у різних точках життєвого циклу сторінки, наприклад перед збереженням форми. Щоб налаштувати хук, створіть protected-метод у класі сторінки Create з назвою хука:
protected function beforeCreate(): void
{
// ...
}
У цьому прикладі код у методі beforeCreate() буде викликано перед тим, як дані форми збережуться в базу.
Для сторінки Create доступно кілька хуків:
use Filament\Resources\Pages\CreateRecord;
class CreateUser extends CreateRecord
{
// ...
protected function beforeFill(): void
{
// Виконується перед тим, як поля форми заповнюються типовими значеннями.
}
protected function afterFill(): void
{
// Виконується після того, як поля форми заповнено типовими значеннями.
}
protected function beforeValidate(): void
{
// Виконується перед валідацією полів форми під час її надсилання.
}
protected function afterValidate(): void
{
// Виконується після валідації полів форми під час її надсилання.
}
protected function beforeCreate(): void
{
// Виконується перед збереженням полів форми в базу даних.
}
protected function afterCreate(): void
{
// Виконується після збереження полів форми в базу даних.
}
}
Якщо ж ви створюєте записи в модальній дії, дивіться документацію по діях.
Визначення хуків життєвого циклу в трейтах
Щоб визначити хук життєвого циклу в трейті, додайте до назви хука суфікс з назвою трейта. Це відповідає угоді boot{TraitName}(), яку використовує Eloquent, і угоді mount{TraitName}() з Livewire, завдяки чому багаторазові трейти можуть вбудовуватися в життєвий цикл сторінки, не конфліктуючи з хуками, визначеними на самій сторінці:
use Filament\Resources\Pages\CreateRecord;
trait HandlesDrafts
{
protected function afterCreateHandlesDrafts(): void
{
// Виконується після збереження полів форми в базу даних, на додачу
// до хука на сторінці.
}
}
class CreateUser extends CreateRecord
{
use HandlesDrafts;
protected function afterCreate(): void
{
// Викликаються обидва хуки життєвого циклу.
}
}
Спочатку викликається власний хук сторінки, потім хук кожного трейта. Хуки з трейтів, які використовуються іншими трейтами, теж викликаються. Хуки трейтів викликаються автоматично, тому не варто додатково викликати їх із власного хука сторінки.
Зупинка процесу створення
Будь-коли ви можете викликати $this->halt() зсередини хука життєвого циклу або методу зміни даних, і це зупинить увесь процес створення:
use Filament\Actions\Action;
use Filament\Notifications\Notification;
protected function beforeCreate(): void
{
if (! auth()->user()->team->subscribed()) {
Notification::make()
->warning()
->title('You don\'t have an active subscription!')
->body('Choose a plan to continue.')
->persistent()
->actions([
Action::make('subscribe')
->button()
->url(route('subscribe'), shouldOpenInNewTab: true),
])
->send();
$this->halt();
}
}
Якщо ж ви створюєте записи в модальній дії, дивіться документацію по діях.
Авторизація
Для авторизації Filament враховує будь-які політики моделей, зареєстровані у вашому застосунку.
Користувачі можуть отримати доступ до сторінки Create, якщо метод create() політики моделі повертає true.
Використання майстра
Процес створення легко перетворити на багатокрокового майстра (wizard).
У класі сторінки додайте відповідний трейт HasWizard:
use App\Filament\Resources\Categories\CategoryResource;
use Filament\Resources\Pages\CreateRecord;
class CreateCategory extends CreateRecord
{
use CreateRecord\Concerns\HasWizard;
protected static string $resource = CategoryResource::class;
protected function getSteps(): array
{
return [
// ...
];
}
}
У масиві getSteps() поверніть свої кроки майстра:
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Schemas\Components\Wizard\Step;
protected function getSteps(): array
{
return [
Step::make('Name')
->description('Give the category a clear and unique name')
->schema([
TextInput::make('name')
->required()
->live()
->afterStateUpdated(fn ($state, callable $set) => $set('slug', Str::slug($state))),
TextInput::make('slug')
->disabled()
->required()
->unique(Category::class, 'slug', fn ($record) => $record),
]),
Step::make('Description')
->description('Add some extra details')
->schema([
MarkdownEditor::make('description')
->columnSpan('full'),
]),
Step::make('Visibility')
->description('Control who can view it')
->schema([
Toggle::make('is_visible')
->label('Visible to customers.')
->default(true),
]),
];
}
Якщо ж ви створюєте записи в модальній дії, дивіться документацію по діях.
Тепер створіть новий запис, щоб побачити майстра в дії! Редагування й далі використовуватиме форму, визначену в класі ресурсу.
Якщо ви хочете дозволити вільну навігацію, щоб усі кроки можна було пропускати, перевизначте метод hasSkippableSteps():
public function hasSkippableSteps(): bool
{
return true;
}
Спільні поля для схеми форми й майстра
Щоб зменшити кількість повторень між формою ресурсу й кроками майстра, зручно винести поля в публічні статичні методи, звідки екземпляр поля легко дістати і для схеми форми, і для майстра:
use Filament\Forms;
use Filament\Schemas\Schema;
class CategoryForm
{
public static function configure(Schema $schema): Schema
{
return $schema
->components([
static::getNameFormField(),
static::getSlugFormField(),
// ...
]);
}
public static function getNameFormField(): Forms\Components\TextInput
{
return TextInput::make('name')
->required()
->live()
->afterStateUpdated(fn ($state, callable $set) => $set('slug', Str::slug($state)));
}
public static function getSlugFormField(): Forms\Components\TextInput
{
return TextInput::make('slug')
->disabled()
->required()
->unique(Category::class, 'slug', fn ($record) => $record);
}
}
use App\Filament\Resources\Categories\Schemas\CategoryForm;
use Filament\Resources\Pages\CreateRecord;
class CreateCategory extends CreateRecord
{
use CreateRecord\Concerns\HasWizard;
protected static string $resource = CategoryResource::class;
protected function getSteps(): array
{
return [
Step::make('Name')
->description('Give the category a clear and unique name')
->schema([
CategoryForm::getNameFormField(),
CategoryForm::getSlugFormField(),
]),
// ...
];
}
}
Імпорт записів ресурсу
Filament містить ImportAction, який можна додати до getHeaderActions() сторінки List. Він дозволяє користувачам завантажити CSV із даними для імпорту в ресурс:
use App\Filament\Imports\ProductImporter;
use Filament\Actions;
protected function getHeaderActions(): array
{
return [
Actions\ImportAction::make()
->importer(ProductImporter::class),
Actions\CreateAction::make(),
];
}
Клас «importer» потрібно створити, щоб пояснити Filament, як імпортувати кожен рядок CSV. Усе про ImportAction можна дізнатися в документації по діях.
Власні дії
«Дії» - це кнопки, що відображаються на сторінках і дозволяють користувачеві виконати метод Livewire на сторінці або перейти за URL.
На сторінках ресурсу дії зазвичай розміщені у 2 місцях: у правому верхньому куті сторінки й під формою.
Наприклад, ви можете додати нову кнопку-дію в заголовку сторінки Create:
use App\Filament\Imports\UserImporter;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateUser extends CreateRecord
{
// ...
protected function getHeaderActions(): array
{
return [
Actions\ImportAction::make()
->importer(UserImporter::class),
];
}
}
Або нову кнопку поруч із «Create» під формою:
use Filament\Actions\Action;
use Filament\Resources\Pages\CreateRecord;
class CreateUser extends CreateRecord
{
// ...
protected function getFormActions(): array
{
return [
...parent::getFormActions(),
Action::make('close')->action('createAndClose'),
];
}
public function createAndClose(): void
{
// ...
}
}
Щоб переглянути весь API дій, зазирніть до розділу про сторінки.
Додавання кнопки дії створення в заголовок
Кнопку «Create» можна перенести в заголовок сторінки, перевизначивши метод getHeaderActions() і скориставшись getCreateFormAction(). Дії потрібно передати formId(), щоб вказати, що вона має надсилати форму з ID form - саме такий ID має <form> у представленні (view) сторінки:
protected function getHeaderActions(): array
{
return [
$this->getCreateFormAction()
->formId('form'),
];
}
Прибрати всі дії з форми можна, перевизначивши метод getFormActions() так, щоб він повертав порожній масив:
protected function getFormActions(): array
{
return [];
}
Власний вміст сторінки
Кожна сторінка у Filament має власну схему, яка визначає загальну структуру й вміст. Схему сторінки можна перевизначити, оголосивши на ній метод content(). Метод content() для сторінки Create типово містить такі компоненти:
use Filament\Schemas\Schema;
public function content(Schema $schema): Schema
{
return $schema
->components([
$this->getFormContentComponent(), // Цей метод повертає компонент для відображення форми, визначеної в цьому ресурсі
]);
}
У масив components() можна вставити будь-який компонент схеми. Компоненти можна переставляти, змінюючи порядок у масиві, або прибирати ті, що не потрібні.
Використання власного Blade-представлення
Для ще ширших можливостей налаштування перевизначте статичну властивість $view у класі сторінки, вказавши власне представлення у вашому застосунку:
protected string $view = 'filament.resources.users.pages.create-user';
Це передбачає, що ви створили представлення за шляхом resources/views/filament/resources/users/pages/create-user.blade.php:
<x-filament-panels::page>
{{ $this->content }} {{-- Це відрендерить вміст сторінки, визначений у методі `content()`; його можна прибрати, якщо хочете почати з нуля --}}
</x-filament-panels::page>
Перекладаємо з офіційної документації, розділ за розділом, і не ховаємо недоперекладене. Помітили неточність у терміні чи реченні: напишіть, виправимо.