FEATURED · 精选文章

Filament CreateAction 完整实战指南:用模态框表单创建 Eloquent 记录的官方实现与源码剖析

发布时间 / 2026/9/11 18:23:37
来源 / 创域科博编辑部
栏目 / 资讯中心
Filament CreateAction 完整实战指南:用模态框表单创建 Eloquent 记录的官方实现与源码剖析 Filament CreateAction 完整实战指南用模态框表单创建 Eloquent 记录的官方实现与源码剖析【免费下载链接】filamentA powerful open-source UI framework for Laravel • Build and ship apps admin panels fast with Livewire项目地址: https://gitcode.com/GitHub_Trending/fi/filamentFilament 内置的CreateAction是构建后台「新建记录」流程的高效组件点击触发按钮即弹出包含表单的模态框提交后自动完成校验、落库、通知与跳转。本文以官方文档 packages/actions/docs/04-create.md 为骨架结合CreateAction源码与测试深入讲解数据预处理、创建流程定制、生命周期钩子、向导式多步表单以及「创建并继续创建」等全部能力读完即可在表格 Action、表单 Action 与资源页面中直接落地使用。一、快速上手一个能落库的创建弹窗在 Filament 中任何「点击按钮 → 弹出表单 → 校验并写入数据库」的需求都可以通过Filament\Actions\CreateAction一行式链式调用完成use Filament\Actions\CreateAction; use Filament\Forms\Components\TextInput; CreateAction::make() -schema([ TextInput::make(title) -required() -maxLength(255), // ... 更多字段 ])当触发按钮被点击时Filament 会打开一个模态框模态框内渲染schema()中定义的字段用户填写并提交后数据经过表单校验被保存为一条新的 Eloquent 记录。从源码来看CreateAction继承自Action并定义了默认行为见 packages/actions/src/CreateAction.php默认名称getDefaultName()返回create默认标签来自语言包filament-actions::create.single.label模态框标题modalHeading、提交按钮文案均使用内置翻译键默认开启「创建另一个」扩展按钮canCreateAnother()默认为true并预置成功通知标题。测试用例也验证了这一基础契约见 tests/src/Actions/CreateActionTest.php在关系管理器中渲染CreateAction、挂载模态框、填充表单、调用 Action 后断言数据库出现对应记录并断言弹出成功通知。二、保存前修改表单数据mutateDataUsing()有些场景需要在数据落库前进行加工例如自动注入当前登录用户 ID、生成时间戳或对字段做归一化。此时使用mutateDataUsing()它接收$data数组并返回修改后的数组use Filament\Actions\CreateAction; CreateAction::make() -mutateDataUsing(function (array $data): array { $data[user_id] auth()-id(); return $data; })该方法不仅支持静态闭包还可以注入 Action 自身的各种工具参数如$action、$livewire、$schema等用于更精细的动态处理。三、完全接管创建过程using()如果默认的「实例化模型 → fill → save」流程无法满足需求例如调用第三方服务、写入额外表、调用模型自定义方法可以用using()完全接管记录的创建逻辑use Filament\Actions\CreateAction; use Illuminate\Database\Eloquent\Model; CreateAction::make() -using(function (array $data, string $model): Model { return $model::create($data); })其中$model是模型类名字符串你也可以在闭包内硬编码自己的模型类。闭包必须返回一个 Eloquent 模型实例。从源码看using()定义于CanCustomizeProcesstraitpackages/actions/src/Concerns/CanCustomizeProcess.php它把闭包存为$this-using而process()方法执行evaluate($this-using ?? $default, $parameters)——即「有自定义则用自定义否则用默认流程」。CreateAction的默认流程见 CreateAction.php相当精细解析getRelationship()判断是否在关联关系上下文中创建若是BelongsToMany关系则把枢轴pivot列从$data中分离出来Arr::only/Arr::except若 Livewire 组件启用了可翻译内容驱动makeFilamentTranslatableContentDriver()通过驱动创建记录否则new $model并fill($data)无关联或HasOneOrManyThrough关系时直接$record-save()普通关联关系通过$relationship-save($record)保存自动维护外键BelongsToMany关系通过$relationship-save($record, $pivotData)同时写入枢轴表。这也解释了为什么在关系管理器中创建的记录能自动挂到父记录下——测试 attaches created record to relationship 专门验证了这一点。四、创建成功后的跳转successRedirectUrl()默认情况下创建成功后 Filament 会停留在当前页面。你可以通过successRedirectUrl()指定跳转目标use Filament\Actions\CreateAction; CreateAction::make() -successRedirectUrl(route(posts.list))如果需要基于刚创建的记录跳转例如跳到编辑页闭包可以注入$record参数use Filament\Actions\CreateAction; use Illuminate\Database\Eloquent\Model; CreateAction::make() -successRedirectUrl(fn (Model $record): string route(posts.edit, [ post $record, ]))其底层实现在 packages/actions/src/Concerns/CanRedirect.phpdispatchSuccessRedirect()会先evaluate自定义 URL若为空则回退到 Livewire 组件的getDefaultActionSuccessRedirectUrl()redirect()方法还会根据是否启用 SPA 模式自动决定是否使用navigate进行前端路由跳转。五、定制成功通知记录创建成功后Filament 会向用户派发一条成功通知。默认标题来自语言包你可以覆盖use Filament\Actions\CreateAction; CreateAction::make() -successNotificationTitle(User registered)标题也支持闭包动态计算。若想定制整条通知类型、标题、正文等使用successNotification()use Filament\Actions\CreateAction; use Filament\Notifications\Notification; CreateAction::make() -successNotification( Notification::make() -success() -title(User registered) -body(The user has been created successfully.), )successNotification()同样接受闭包闭包内可注入默认的$notification对象作为定制起点。完全禁用通知则传入nulluse Filament\Actions\CreateAction; CreateAction::make() -successNotification(null)从 CanNotify 源码可以看出传入null时isSuccessNotificationDisabled会被置为truesendSuccessNotification()直接短路返回发送前还会检查通知标题是否为空filled($notification?-getTitle())空标题不发送。注意该 trait 同时提供了failureNotification()、unauthorizedNotification()、rateLimitedNotification()等配套方法但CreateAction主要使用成功通知。六、生命周期钩子在创建流程的关键节点注入代码Filament 为创建流程提供了 6 个生命周期钩子覆盖「表单填充默认值 → 校验 → 保存」的完整链路use Filament\Actions\CreateAction; CreateAction::make() -beforeFormFilled(function () { // 表单字段填充默认值之前执行 }) -afterFormFilled(function () { // 表单字段填充默认值之后执行 }) -beforeFormValidated(function () { // 表单提交、字段校验之前执行 }) -afterFormValidated(function () { // 表单字段校验通过之后执行 }) -before(function () { // 表单字段保存到数据库之前执行 }) -after(function () { // 表单字段保存到数据库之后执行 })钩子定义与调用在 packages/actions/src/Concerns/HasLifecycleHooks.php 中每个before*/after*方法只是把闭包存入对应属性callBefore()/callAfter()等call*方法负责evaluate执行。值得注意的实现细节是callBefore()会先派发ActionCalling事件而callAfter()在闭包执行完毕后finally块中派发ActionCalled事件——这意味着钩子与事件系统是联动的你可以在全局监听这些事件对 Action 调用做统一埋点或审计。七、中断或取消创建流程halt() 与 cancel()你可以在任何生命周期钩子或数据处理方法中调用$action-halt()中断整个创建流程。一个典型场景是订阅校验use App\Models\Post; use Filament\Actions\Action; use Filament\Actions\CreateAction; use Filament\Notifications\Notification; CreateAction::make() -before(function (CreateAction $action, Post $record) { if (! $record-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(); $action-halt(); } })如果你希望模态框也随之关闭则改用cancel()完全取消 Action$action-cancel();两者的底层实现packages/actions/src/Action.php都是抛出专用异常来中断执行流cancel()抛出Cancelhalt()抛出Halt并且都支持$shouldRollBackDatabaseTransaction参数——结合CanUseDatabaseTransactions使用时可以回滚当前数据库事务。区别在于Cancel会让整个 Action 流程终止且模态框关闭而Halt仅中断流程、保留模态框状态。halt()还有一个已弃用的别名hold()。八、把创建流程变成多步向导steps()当新建表单字段较多时可以将其拆分为多步向导Wizard。不再使用schema()而是通过steps()传入一组Step对象use Filament\Actions\CreateAction; use Filament\Forms\Components\MarkdownEditor; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; use Filament\Schemas\Components\Wizard\Step; CreateAction::make() -steps([ Step::make(Name) -description(Give the category a 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), ]) -columns(2), Step::make(Description) -description(Add some extra details) -schema([ MarkdownEditor::make(description), ]), Step::make(Visibility) -description(Control who can view it) -schema([ Toggle::make(is_visible) -label(Visible to customers.) -default(true), ]), ])每个Step都可以独立设置描述、字段 schema 与栅格列数columns(2)。Step类位于 schemas 包的Filament\Schemas\Components\Wizard\Step与表单/表格中使用的向导组件同源。文档同时提醒这种「创建即向导」的方式只影响创建 Action 本身编辑Edit仍使用资源类中定义的表单。如果希望所有步骤都可自由跳转不再强制按顺序填写追加skippableSteps()use Filament\Actions\CreateAction; CreateAction::make() -steps([ // ... ]) -skippableSteps()九、「创建并继续创建」提升录入效率的进阶能力CreateAction 的模态框底部默认带有「创建另一个」按钮允许用户连续录入多条记录非常适合后台批量录入场景。9.1 定制「创建另一个」按钮通过createAnotherAction()传入一个返回 Action 的闭包来修改按钮闭包接收$action参数所有可用的触发按钮定制方法都可使用use Filament\Actions\CreateAction; CreateAction::make() -createAnotherAction(fn (Action $action): Action $action-label(Custom create another label))源码CreateAction.php中getCreateAnotherAction()通过makeModalSubmitAction(createAnother, arguments: [another true])生成默认按钮再交由modifyCreateAnotherActionUsing闭包改写测试 can modify the create another action 验证了将标签改为Save New后getLabel()返回正确结果。9.2 移除「创建另一个」按钮use Filament\Actions\CreateAction; CreateAction::make() -createAnother(false)createAnother()接受布尔值或闭包bool | Closure默认true。与之等价的旧方法disableCreateAnother()已标记为弃用官方推荐统一使用createAnother(false)。相关测试见 tests/src/Actions/CreateActionTest.php覆盖了布尔值与闭包两种赋值方式。9.3 保留表单数据preserveFormDataWhenCreatingAnother()默认情况下「创建另一个」会清空整个表单让用户重新开始。若想保留部分字段例如is_admin、organization这类每条记录都相同的值传入字段名数组use Filament\Actions\CreateAction; CreateAction::make() -preserveFormDataWhenCreatingAnother([is_admin, organization])也可以传入一个函数从$data中挑选要保留的数据use Filament\Actions\CreateAction; use Illuminate\Support\Arr; CreateAction::make() -preserveFormDataWhenCreatingAnother(fn (array $data): array Arr::only($data, [is_admin, organization]))甚至返回整个$data来保留所有数据use Filament\Actions\CreateAction; CreateAction::make() -preserveFormDataWhenCreatingAnother(fn (array $data): array $data)其内部实现CreateAction.php是传入数组时自动包装为Arr::only($data, $fields)的闭包传入闭包时原样保存。测试覆盖了保留标量字段与保留 Repeater 复杂结构两种场景tests/src/Actions/CreateActionTest.php并验证了「创建另一个」后autofocus()字段会通过reset-schema-component-state事件重新聚焦L130-L142。9.4 创建另一个背后的完整流程结合 CreateAction.php 的action()实现可以还原「创建另一个」的完整链路检测参数$arguments[another]若为true先取出待保留的原始状态$preserveRawState执行创建流程含mutateDataUsing与using记录创建成功后发送成功通知 → 重置$record为null→ 用空模型重建 schema →schema-fill()重新填充默认值 → 将保留的数据合并回rawState→ 派发reset-schema-component-state客户端事件调用$this-halt()结束本轮模态框保持打开等待下一次提交。此外forceRenderAfterCreateAnother()可以强制 Livewire 组件在「创建另一个」后重新渲染适用于某些需要刷新列表或关联数据的场景默认关闭测试见 L257-L265。十、小结与实战建议至此FilamentCreateAction的核心能力已全部覆盖模态框 表单的快速创建、mutateDataUsing()数据预处理、using()全接管、successRedirectUrl()智能跳转、成功通知定制、6 个生命周期钩子、halt()/cancel()流程控制、多步向导以及「创建并继续创建」的完整增强能力。根据源码与测试几点实战建议关系上下文自动处理在 Relation Manager 或带relationship()的 Action 中默认创建流程会自动维护外键与枢轴表无需手写关联保存逻辑钩子与事件联动before/after钩子会同步派发ActionCalling/ActionCalled事件可据此做全局审计事务一致性halt()/cancel()支持$shouldRollBackDatabaseTransaction参数在需要原子性的流程中结合数据库事务使用向导与资源表单分离创建向导只影响 CreateAction 本身编辑表单仍由资源类定义两者互不干扰。相关参考Actions 总览、编辑 Action、视图 Action、Form 组件文档、Schema / 布局组件。【免费下载链接】filamentA powerful open-source UI framework for Laravel • Build and ship apps admin panels fast with Livewire项目地址: https://gitcode.com/GitHub_Trending/fi/filament创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻