尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Filament 开发实战指南:从表单布局到测试覆盖的完整模式手册

Filament 开发实战指南:从表单布局到测试覆盖的完整模式手册 Filament 开发实战指南从表单布局到测试覆盖的完整模式手册【免费下载链接】filamentA powerful open-source UI framework for Laravel • Build and ship apps admin panels fast with Livewire项目地址: https://gitcode.com/GitHub_Trending/fi/filamentFilament 是构建在 Laravel、Livewire、Alpine.js 与 Tailwind CSS 之上的 UI 框架本指南以当前仓库packages/panels/resources/boost/skills/filament-development/SKILL.md为核心骨架系统梳理开发 Filament 面板Panel时的高频模式组件初始化与响应式状态、布局组合、关系型表单、表格过滤、动作与模态框以及基于 Pest Livewire 的完整测试套路。读完本文你将掌握一套可复制的写代码—跑命令—写测试开发闭环并理解每个模式背后的源码实现位置。Filament 开发的心智模型Filament 界面完全通过 PHP 定义组件是**流式fluent、可链式调用chainable**的对象以静态make()方法初始化再用-method()链式配置。所有界面逻辑——表单、表格、页面、动作、信息展示infolist、部件widget、导入导出——都是这套组件模型的实例。在动手前请注意两条核心开发纪律优先使用 Filament 专属 Artisan 命令生成文件可通过list-artisan-commands工具或运行php artisan list查看可用命令执行前先检查必需选项并始终传入--no-interaction以保证命令在非交互环境CI、脚本下可稳定执行。动态值用Closure大多数配置方法都接受闭包Closure来求值动态内容例如根据当前记录或表单状态决定可见性、选项、样式。这正是 Filament PHP 即 UI 的关键——把逻辑内联到组件定义中而不是散落在 Blade 模板里。组件初始化与响应式状态静态make()与闭包求值所有组件都通过SomeComponent::make(name)创建命名一般对应模型字段或关系名。例如use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; Select::make(type)-required()-live(); TextInput::make(company_name)-required();这里-required()是静态校验规则而下面的-visible()则展示了闭包动态求值的用法。条件表单字段可见性Get最常见的动态行为是根据另一个字段的值决定当前字段是否显示。模式是用-live()让type字段的状态变化实时同步到 Livewire 组件然后通过Get注入器读取其他字段值use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Schemas\Components\Utilities\Get; Select::make(type) -options(CompanyType::class) -required() -live(), TextInput::make(company_name) -required() -visible(fn (Get $get): bool $get(type) business),源码印证Get类 是一个可调用对象__invoke它基于当前组件解析相对状态路径resolveRelativeStatePath先在根容器中按状态路径找到目标组件并返回其getState()若找不到组件则回退到data_get($livewire, $path)读取 Livewire 数据。这解释了为什么$get(type)既能读到表单字段也能读到组件外部的 Livewire 属性。Get还提供string()、float()、boolean()等类型化读取方法适合需要严格类型判断的场景。响应式字段更新Set另一个高频需求是一个字段变化时联动更新另一个字段典型例子是标题自动生成 slug。在-live()字段上挂-afterStateUpdated()通过Set注入器写入目标字段use Filament\Schemas\Components\Utilities\Set; use Illuminate\Support\Str; TextInput::make(title) -required() -live(onBlur: true) -afterStateUpdated(fn (Set $set, ?string $state) $set( slug, Str::slug($state ?? ), )), TextInput::make(slug) -required(),值得注意的细节文本输入建议使用-live(onBlur: true)而非默认的每键实时更新以避免每次击键都触发一次网络请求。这对长表单的性能体验至关重要。Set与Get同处Filament\Schemas\Components\Utilities命名空间二者组合即可构建出复杂的表单联动逻辑。布局组合Section与Grid表单/页面的布局通过嵌套Section与Grid组件完成。默认情况下子组件只占一列必须显式指定跨列use Filament\Schemas\Components\Grid; use Filament\Schemas\Components\Section; Section::make(Details) -schema([ Grid::make(2)-schema([ TextInput::make(first_name), TextInput::make(last_name), TextInput::make(bio) -columnSpanFull(), ]), ]),Grid::make(2)创建两列栅格字段按顺序自动流入各列-columnSpan()控制跨越的列数如-columnSpan(2)-columnSpanFull()表示占满整行Section::make(Details)生成带标题的分区卡片让表单在视觉上分组清晰。这是新手最容易踩的坑之一不要假设默认全宽。Grid、Section、Fieldset、Repeater默认都不会横跨所有列需要跨行时必须显式声明。关系型表单Repeater内联管理HasMany当需要在同一个表单里编辑一对多关系时用Repeater内联管理子记录。-relationship()不传参数时会自动绑定与字段名同名复数化的 Eloquent 关系use Filament\Forms\Components\Repeater; Repeater::make(qualifications) -relationship() -schema([ TextInput::make(institution) -required(), TextInput::make(qualification) -required(), ]) -columns(2);源码印证Repeater::relationship()的签名是relationship(string | Closure | null $name null, ...)$name默认为null即回退到与 Repeater 字段名匹配的关系名。它同时支持$modifyQueryUsing与$modifyRecordsUsing两个闭包分别用于约束关系查询与在保存前调整子记录集合。注意 Repeater 内部子字段用的是-schema()不是-fields()。对于BelongsTo外键字段正确的做法是Select::make(author_id)-relationship(author, name)——BelongsToSelect组件并不存在Select::relationship()才是标准写法。表格计算列、过滤器与动作用state()闭包计算派生列当列需要展示由记录多个字段派生的值时用state()传入闭包计算use Filament\Tables\Columns\TextColumn; TextColumn::make(full_name) -state(fn (User $record): string {$record-first_name} {$record-last_name}),闭包接收当前$record返回字符串即可。此时列的namefull_name仅作标识实际展示内容由闭包决定。表格过滤器SelectFilter与自定义Filter枚举或关系类型的筛选用SelectFilter直接绑定枚举类或关系字段use Filament\Tables\Filters\Filter; use Filament\Tables\Filters\SelectFilter; use Illuminate\Database\Eloquent\Builder; SelectFilter::make(status) -options(UserStatus::class), SelectFilter::make(author) -relationship(author, name),需要自定义查询逻辑时用基础Filter搭配-query()闭包Filter::make(verified) -query(fn (Builder $query) $query-whereNotNull(email_verified_at)),源码印证-query()定义在InteractsWithTableQuery这个 Concern 中它接收一个?Closure并存储为回调在应用过滤时以当前查询构造器调用——这正是自定义过滤逻辑能直接where的原因。动作Action与模态表单Action 是封装按钮 可选模态框 行为的完整单元。最灵活的是自定义Action它可以内嵌一个模态表单收集数据再在-action()闭包里执行业务逻辑use Filament\Actions\Action; Action::make(updateEmail) -schema([ TextInput::make(email) -email() -required(), ]) -action(fn (array $data, User $record) $record-update($data)),要点解读-schema()中的字段构成模态框内的表单-action()闭包接收$data模态表单收集的数组与$record当前行记录在此处完成持久化传入动作构造器的$record由调用方提供页面动作自动绑定当前记录表格动作需显式指定-table($record)。命名空间红线动作类统一使用Filament\Actions\命名空间如Filament\Actions\Action、DeleteAction、CreateAction绝不使用Filament\Tables\Actions\、Filament\Forms\Actions\或其他子命名空间。仓库中packages/actions/src/Action.php的命名空间声明即为此约定的直接证据。图标则应使用Filament\Support\Icons\Heroicon枚举如Heroicon::PencilSquare该枚举定义于packages/support/src/Icons/Heroicon.php。测试Pest Livewire 驱动的面板测试测试面板功能需要安装pestphp/pest-plugin-livewire声明于composer.json并用use function Pest\Livewire\livewire引入辅助函数。测试前必须先$this-actingAs(User::factory()-create())模拟已认证用户。表格测试use function Pest\Livewire\livewire; livewire(ListUsers::class) -assertCanSeeTableRecords($users) -searchTable($users-first()-name) -assertCanSeeTableRecords($users-take(1)) -assertCanNotSeeTableRecords($users-skip(1));依次断言初始能看到全部记录 → 执行搜索后只剩匹配记录 → 不匹配的记录不可见。创建资源测试use function Pest\Laravel\assertDatabaseHas; livewire(CreateUser::class) -fillForm([ name Test, email testexample.com, ]) -call(create) -assertNotified() -assertHasNoFormErrors() -assertRedirect(); assertDatabaseHas(User::class, [ name Test, email testexample.com, ]);创建页默认在成功后重定向因此可以断言-assertRedirect()。编辑资源测试livewire(EditUser::class, [record $user-id]) -fillForm([name Updated]) -call(save) -assertNotified() -assertHasNoFormErrors(); assertDatabaseHas(User::class, [ id $user-id, name Updated, ]);关键差异编辑页传入[record $user-id]且调用-call(save)不是-call(create)编辑页默认保存后不重定向因此除非显式配置了重定向或重写了getRedirectUrl()否则不要断言-assertRedirect()。校验失败测试livewire(CreateUser::class) -fillForm([ name null, email invalid-email, ]) -call(create) -assertHasFormErrors([ name required, email email, ]) -assertNotNotified();用assertHasFormErrors断言具体规则required、email并用assertNotNotified()确认失败时不会弹出成功通知。调用动作Action页面动作用-callAction(DeleteAction::class)表格动作则需要TestAction::make(name)-table($record)绑定目标记录use Filament\Actions\Testing\TestAction; livewire(ListUsers::class) -callAction(TestAction::make(promote)-table($user), [ role admin, ]) -assertNotified();TestAction定义于packages/actions/src/Testing/TestAction.php它把真实的Action对象暴露给测试层第二个参数传入模态表单数据。仓库中tests/src/Actions/下的测试套件如ActionTest.php、ModalTest.php、RateLimitingTest.php是这套 API 的完整实战范例。正确命名空间速查表组件类别命名空间表单字段TextInput、Select、Repeater等Filament\Forms\Components\Infolist 条目TextEntry、IconEntry等Filament\Infolists\Components\布局组件Grid、Section、Fieldset、Tabs、Wizard等Filament\Schemas\Components\Schema 工具类Get、Set等Filament\Schemas\Components\Utilities\表格列TextColumn、IconColumn等Filament\Tables\Columns\表格过滤器SelectFilter、Filter等Filament\Tables\Filters\动作DeleteAction、CreateAction等Filament\Actions\禁用子命名空间图标Filament\Support\Icons\Heroicon枚举常见错误清单不要假设文件公开可见文件可见性默认是private需要公开访问时必须显式-visibility(public)。不要假设全宽布局Grid、Section、Fieldset、Repeater默认不跨所有列需用-columnSpan()/-columnSpanFull()显式控制。BelongsTo字段用Select::make(author_id)-relationship(author, name)不存在BelongsToSelect。Repeater使用-schema()不是-fields()。不要给需要保存的字段加-dehydrated(false)它会在-action()或保存处理器运行前把该字段从表单状态中剥离仅适合辅助/纯 UI 字段。重写属性时保持正确的类型声明$navigationIconprotected static string | BackedEnum | null不是?string$navigationGroupprotected static string | UnitEnum | null不是?string$view在Page与Widget类中是protected string不是protected static string。结语这份技能文档浓缩了 Filament 开发中最高频的实战模式用make() 闭包构建响应式 UI、用Get/Set串联字段联动、用Section/Grid组织布局、用Repeater内联管理关系、用SelectFilter/Filter做表格筛选、用Action封装模态交互最后用 Pest Livewire 覆盖全部面板功能。遵循本文的命名空间约定与常见错误清单配合仓库中packages/各模块源码与tests/测试套件即可在现有代码库中保持一致的 Filament 开发风格快速交付可测试、可维护的管理面板功能。【免费下载链接】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),仅供参考
返回列表