创建记录


保存前自定义数据
有时,你可能希望在数据最终写入数据库前修改表单数据。可在创建页类上定义 mutateFormDataBeforeCreate(),接收 $data 数组并返回修改后的版本:
protected function mutateFormDataBeforeCreate(array $data): array
{
$data['user_id'] = auth()->id();
return $data;
}或者,若在模态操作中创建记录,请参阅 操作文档。
自定义创建过程
可用创建页类上的 handleRecordCreation() 方法调整记录的创建方式:
use Illuminate\Database\Eloquent\Model;
protected function handleRecordCreation(array $data): Model
{
return static::getModel()::create($data);
}或者,若在模态操作中创建记录,请参阅 操作文档。
自定义重定向
可通过覆盖创建页类上的 getRedirectUrl(),在保存表单时设置自定义重定向。
例如,表单可重定向回 列表页:
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') // or
->resourceCreatePageRedirect('view') // or
->resourceCreatePageRedirect('edit');
}自定义保存通知
记录成功创建后,会向用户派发通知,表明操作成功。
要自定义该通知的标题,在创建页类上定义 getCreatedNotificationTitle() 方法:
protected function getCreatedNotificationTitle(): ?string
{
return 'User registered';
}或者,若在模态操作中创建记录,请参阅 操作文档。
可通过覆盖创建页类上的 getCreatedNotification() 自定义整个通知:
use Filament\Notifications\Notification;
protected function getCreatedNotification(): ?Notification
{
return Notification::make()
->success()
->title('User registered')
->body('The user has been created successfully.');
}要完全禁用通知,从创建页类的 getCreatedNotification() 返回 null:
use Filament\Notifications\Notification;
protected function getCreatedNotification(): ?Notification
{
return null;
}再创建一条记录
禁用「再创建一条」
要禁用「创建并再创建一条」功能,在创建页类上将 $canCreateAnother 属性定义为 false:
protected static bool $canCreateAnother = false;或者,若希望用动态条件决定何时禁用该功能,可覆盖创建页类上的 canCreateAnother() 方法:
public function canCreateAnother(): bool
{
return false;
}再创建时保留数据
默认情况下,用户使用「创建并再创建一条」时,表单数据会全部清空以便重新填写。若希望保留部分表单数据,可覆盖创建页类上的 preserveFormDataWhenCreatingAnother(),并返回希望保留的 $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 方法:
protected function beforeCreate(): void
{
// ...
}在此例中,beforeCreate() 中的代码会在表单数据写入数据库之前调用。
创建页有若干可用钩子:
use Filament\Resources\Pages\CreateRecord;
class CreateUser extends CreateRecord
{
// ...
protected function beforeFill(): void
{
// Runs before the form fields are populated with their default values.
}
protected function afterFill(): void
{
// Runs after the form fields are populated with their default values.
}
protected function beforeValidate(): void
{
// Runs before the form fields are validated when the form is submitted.
}
protected function afterValidate(): void
{
// Runs after the form fields are validated when the form is submitted.
}
protected function beforeCreate(): void
{
// Runs before the form fields are saved to the database.
}
protected function afterCreate(): void
{
// Runs after the form fields are saved to the database.
}
}或者,若在模态操作中创建记录,请参阅 操作文档。
在 trait 中定义生命周期钩子
要在 trait 中定义生命周期钩子,请在钩子名后加上 trait 名称。这遵循 Eloquent 的 boot{TraitName}() 与 Livewire 的 mount{TraitName}() 约定,使可复用 trait 能接入页面生命周期,又不会与页面自身定义的钩子冲突:
use Filament\Resources\Pages\CreateRecord;
trait HandlesDrafts
{
protected function afterCreateHandlesDrafts(): void
{
// Runs after the form fields are saved to the database, in addition
// to the hook on the page.
}
}
class CreateUser extends CreateRecord
{
use HandlesDrafts;
protected function afterCreate(): void
{
// Both lifecycle hooks are called.
}
}页面自身的钩子先调用,随后是各个 trait 钩子。其他 trait 所使用的 trait 中的钩子也会被调用。Trait 钩子会自动调用,因此不应再从页面自身的钩子中调用它们。
中止创建过程
可随时在生命周期钩子或变更方法中调用 $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() 方法返回 true,用户即可访问创建页。
使用向导
你可以轻松将创建过程变为多步向导。
在页面类上添加对应的 HasWizard trait:
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;
}在表单 schema 与向导之间共享字段
若希望减少资源表单与向导步骤之间的重复,建议将字段提取为公开静态表单函数,以便从 form schema 或向导中轻松获取字段实例:
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()。它允许用户上传 CSV 数据以导入到资源中:
use App\Filament\Imports\ProductImporter;
use Filament\Actions;
protected function getHeaderActions(): array
{
return [
Actions\ImportAction::make()
->importer(ProductImporter::class),
Actions\CreateAction::make(),
];
}自定义操作
「操作」是显示在页面上的按钮,允许用户运行页面上的 Livewire 方法或访问 URL。
在资源页面上,操作通常出现在两处:页面右上角,以及表单下方。
例如,可在创建页页眉添加新的按钮操作:
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,请访问 页面部分。
将创建操作按钮添加到页眉
可通过覆盖 getHeaderActions() 并使用 getCreateFormAction(),将「Create」按钮移到页面页眉。需要向操作传入 formId(),指明应提交 ID 为 form 的表单,这是页面视图中使用的 <form> ID:
protected function getHeaderActions(): array
{
return [
$this->getCreateFormAction()
->formId('form'),
];
}可通过覆盖 getFormActions() 返回空数组,移除表单上的所有操作:
protected function getFormActions(): array
{
return [];
}

自定义页面内容
Filament 中每个页面都有自己的 schema,定义整体结构与内容。可通过定义 content() 方法覆盖页面 schema。创建页的 content() 默认包含以下组件:
use Filament\Schemas\Schema;
public function content(Schema $schema): Schema
{
return $schema
->components([
$this->getFormContentComponent(), // This method returns a component to display the form that is defined in this resource
]);
}在 components() 数组中可插入任意 schema 组件。可通过调整数组顺序重排组件,或移除不需要的组件。
使用自定义 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 }} {{-- This will render the content of the page defined in the `content()` method, which can be removed if you want to start from scratch --}}
</x-filament-panels::page>