有时,您可能希望在表单数据最终保存到数据库之前对其进行修改。为此,您可以在创建页面类上定义一个 mutateFormDataBeforeCreate() 方法,该方法接受 $data 作为一个数组,并返回修改后的版本:
protected function mutateFormDataBeforeCreate(array $data): array
{
$data['user_id'] = auth()->id();
return $data;
}或者,如果您正在模态操作中创建记录,请查阅操作文档。
您可以使用 Create 页面类上的 handleRecordCreation() 方法来调整记录的创建方式:
use Illuminate\Database\Eloquent\Model;
protected function handleRecordCreation(array $data): Model
{
return static::getModel()::create($data);
}或者,如果你正在模态操作中创建记录,请查阅操作文档。
默认情况下,保存表单后,用户将被重定向到编辑页面 该资源的,或者查看页面如果存在。
您可以在表单保存时,通过重写 Create 页面类上的 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;
}钩子可用于在页面生命周期内的不同时间点执行代码,例如在表单保存之前。要设置钩子,请在 Create 页面类上创建一个受保护的方法,其名称与钩子名称一致:
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.
}
}另一种情况是,如果你在模态操作中创建记录,请查看 操作文档.
在任何时候,您都可以从生命周期钩子或变异方法内部调用 $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;
}如果您想减少资源表单和向导步骤之间的重复量,最好为您的字段提取公共静态表单函数,在此您可以轻松地从表单架构或向导中检索字段实例:
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(),
];
}"importer" 类 需要创建,以告知 Filament 如何导入 CSV 的每一行。您可以在 动作文档 中了解有关 ImportAction 的所有内容。
"操作" 是显示在页面上的按钮,允许用户在页面上运行 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),
];
}
}或者,在表单下方“创建”旁边的一个新按钮:
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
{
// ...
}
}要查看完整的 actions API,请访问 页面部分。
“创建”按钮可以通过覆盖 getHeaderActions() 方法并使用 getCreateFormAction() 将其移动到页面标题。您需要将 formId() 传递给该操作,以指定该操作应提交 ID 为 form 的表单,该 form 是页面视图中使用的 <form> ID:
protected function getHeaderActions(): array
{
return [
$this->getCreateFormAction()
->formId('form'),
];
}您可以从表单中移除所有操作,通过覆盖 getFormActions() 方法使其返回一个空数组:
protected function getFormActions(): array
{
return [];
}Filament 中的每个页面都有自己的 模式,它定义了整体结构和内容。你可以通过在该页面上定义一个 content() 方法来覆盖页面的模式。Create 页面的 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 组件。你可以通过改变数组的顺序来重新排序组件,或者移除任何不需要的组件。
为了进一步的定制化机会,你可以在页面类上覆盖静态的 $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>