Filament 资源记录删除与软删除完整指南:DeleteAction、TrashedFilter 与授权控制
【免费下载链接】filamentA powerful open-source UI framework for Laravel • Build and ship apps & admin panels fast with Livewire项目地址: https://gitcode.com/GitHub_Trending/fi/filament
本文围绕 Filament(基于 Laravel + Livewire 的开源 UI 框架)资源系统中"删除记录"这一核心操作展开,系统讲解在 列表页删除记录、为资源启用软删除(soft-deletes)、恢复(Restore)与强制删除(Force Delete)的完整配置方式,并结合本仓库 packages/actions 与 packages/tables 源码,深入剖析各 Action 的默认行为、TrashedFilter 的查询逻辑以及基于模型 Policy 的授权机制。读完本文,你将能够独立为自己的 Filament 资源接入"删除 → 回收站筛选 → 恢复/强制删除"的完整生命周期,并精确控制单条删除与批量删除的权限边界。
概述:Filament 中的删除操作体系
在 Filament 中,"删除记录"不是一个单一功能,而是一组由 packages/actions 提供的 Action 类组成的完整体系,包括:
| Action 类 | 默认名称 | 典型用途 | 底层调用 |
|---|---|---|---|
| DeleteAction | delete | 删除单条记录(软删除模型则软删除) | $record->delete() |
| DeleteBulkAction | delete(批量场景) | 表格中批量删除多条记录 | 批量查询->delete()或逐条删除 |
| ForceDeleteAction | forceDelete | 强制物理删除软删除记录 | $record->forceDelete() |
| RestoreAction | restore | 恢复已软删除的记录 | $record->restore() |
| TrashedFilter | trashed | 表格筛选:含回收站 / 仅回收站 | withTrashed()/onlyTrashed() |
默认情况下,应用不会展示已删除记录的交互入口;只有当模型使用 Laravel 的SoftDeletestrait 且资源显式接入软删除相关组件后,恢复、强制删除与回收站筛选才会生效。
处理软删除(Soft-deletes)
创建带软删除能力的资源
如果希望资源具备"恢复、强制删除、筛选回收站记录"的能力,最简单的方式是在生成资源时使用--soft-deletes标志:
php artisan make:filament-resource Customer --soft-deletes该标志由 MakeResourceCommand 定义(InputOption,VALUE_NONE类型),其描述为 "Indicate if the model uses soft-deletes"。命令执行时会自动检测模型是否使用SoftDeletes,并把删除/恢复/强制删除相关的表格动作、筛选器与编辑页头部动作一并生成到资源中。
为已有资源添加软删除功能
对于已经存在的资源,可以按下面步骤手动接入软删除能力。
首先更新资源的table()方法。需要引入相关 Action 与筛选器类,注册TrashedFilter、单条记录动作与批量动作:
use Filament\Actions\BulkActionGroup; use Filament\Actions\DeleteAction; use Filament\Actions\DeleteBulkAction; use Filament\Actions\ForceDeleteAction; use Filament\Actions\ForceDeleteBulkAction; use Filament\Actions\RestoreAction; use Filament\Actions\RestoreBulkAction; use Filament\Tables\Filters\TrashedFilter; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; public static function table(Table $table): Table { return $table ->columns([ // ... ]) ->filters([ TrashedFilter::make(), // ... ]) ->recordActions([ // 使用 simple resource(单页资源)或希望不离开表格直接删除记录时, // 可以把这些动作挂在表格行上。 DeleteAction::make(), ForceDeleteAction::make(), RestoreAction::make(), // ... ]) ->toolbarActions([ BulkActionGroup::make([ DeleteBulkAction::make(), ForceDeleteBulkAction::make(), RestoreBulkAction::make(), // ... ]), ]); }接着,覆盖资源的路由绑定查询,移除SoftDeletingScope全局作用域,否则已删除的记录将无法通过路由绑定被解析:
public static function getRecordRouteBindingEloquentQuery(): Builder { return parent::getRecordRouteBindingEloquentQuery() ->withoutGlobalScopes([ SoftDeletingScope::class, ]); }最后,如果存在编辑页(Edit page),在其getHeaderActions()中加入对应动作:
use Filament\Actions; protected function getHeaderActions(): array { return [ Actions\DeleteAction::make(), Actions\ForceDeleteAction::make(), Actions\RestoreAction::make(), // ... ]; }动作的可见性逻辑(源码剖析)
从源码看,Filament 会根据记录的软删除状态自动控制上述动作的显隐,无需手工visible():
- DeleteAction 通过
hidden()判断:若模型存在trashed()方法且记录处于已删除状态,则隐藏删除按钮——即"已删除的记录不能再普通删除"。 - ForceDeleteAction 与 RestoreAction 通过
visible()判断:仅当记录存在trashed()方法且确实处于已删除状态时才显示。这保证了"强制删除/恢复"按钮只出现在回收站记录上。 - DeleteBulkAction 则根据
TrashedFilter的当前状态隐藏自身:当回收站筛选被激活且选择的是"仅回收站"时,批量删除按钮被隐藏(此时应改用批量强制删除)。
三个 Action 均默认使用danger色(Restore 为gray)、要求二次确认弹窗(requiresConfirmation()),并提供成功/失败通知。另外 DeleteAction 还注册了mod+d键盘快捷键,方便桌面端快速操作。
TrashedFilter 的查询行为(源码剖析)
TrashedFilter 继承自TernaryFilter(三态筛选器),提供了三个选项:
- 包含已删除记录(with trashed):
$query->withTrashed() - 仅已删除记录(only trashed):
$query->onlyTrashed() - 默认(不含已删除):
$query->withoutTrashed()
其baseQuery()会调用$query->withoutGlobalScopes([SoftDeletingScope::class]),确保筛选器本身能读取到回收站数据。同时它实现了indicateUsing(),当筛选生效时会在表格上方生成对应的状态指示器,帮助用户明确当前视图是"含回收站"还是"仅回收站"。
在列表页删除记录
表格默认支持批量删除(toolbarActions中的DeleteBulkAction)。如果还需要在表格行上直接删除单条记录,可以在recordActions中加入DeleteAction:
use Filament\Actions\DeleteAction; use Filament\Tables\Table; public static function table(Table $table): Table { return $table ->columns([ // ... ]) ->recordActions([ // ... DeleteAction::make(), ]); }点击行上的删除按钮后,Filament 会弹出确认模态框(modal),确认后执行$record->delete()。若模型启用了软删除,delete()实际执行的是软删除;若未启用,则是物理删除。删除成功后显示成功通知,失败则显示失败通知。
对于批量删除,DeleteBulkAction 的底层实现有两种路径:当不需要逐条授权(默认)时,直接对选中记录的查询执行->delete()(一条 SQL 完成,性能最优);当启用逐条授权时,则遍历每条记录调用$record->delete(),并对失败计数,最终通过通知区分"全部成功 / 部分成功 / 全部失败"三种结果(对应语言包中的deleted、deleted_partial、deleted_none文案)。批量删除完成后会自动取消已选记录(deselectRecordsAfterCompletion())。
授权(Authorization)
Filament 的删除操作会遵循应用中注册的 Laravel 模型策略(Model Policies),无需额外配置。
单条删除与批量删除
- 当策略的
delete()方法返回true时,用户允许删除单条记录。 - 批量删除(bulk delete)则检查策略的
deleteAny()方法。Filament 之所以使用deleteAny()而非逐条检查delete(),是因为对多条记录逐一调用策略方法性能开销过大。
如果业务上确实需要"批量删除时逐条校验delete()",可以在DeleteBulkAction上调用authorizeIndividualRecords():
DeleteBulkAction::make()->authorizeIndividualRecords()该方法定义在 CanBeAuthorized trait 中,支持布尔值、字符串能力名(Gate::inspect)或闭包三种形式;启用后批量删除将进入逐条授权与逐条处理模式,未通过授权的记录会被跳过并计入失败通知。需要说明的是,逐条授权会牺牲批量删除的部分性能,仅在严格权限场景下推荐使用。
软删除的授权
针对软删除的三个阶段,Filament 使用了独立的策略方法:
| 操作 | 单条记录策略方法 | 批量操作策略方法 |
|---|---|---|
| 强制删除 | forceDelete() | forceDeleteAny() |
| 恢复 | restore() | restoreAny() |
forceDelete()用于阻止单条已软删除记录被强制物理删除;forceDeleteAny()用于阻止批量强制删除。restore()用于阻止单条已软删除记录被恢复;restoreAny()用于阻止批量恢复。- 与
deleteAny()同理,批量场景使用forceDeleteAny()和restoreAny()也是出于性能考虑,避免逐条迭代检查。
因此,只要在对应模型的 Policy 中定义好这六个方法(或其中需要约束的部分),Filament 的删除、强制删除、恢复及对应的批量操作就会自动遵循授权结果,未授权时按钮会被隐藏或操作被拦截。
实战建议与常见陷阱
- 路由绑定必须移除全局作用域:为已有资源添加软删除时,务必覆盖
getRecordRouteBindingEloquentQuery()并withoutGlobalScopes([SoftDeletingScope::class]),否则访问已删除记录的编辑页会直接 404。 - 动作显隐是自动的:
DeleteAction在记录已删除时自动隐藏,ForceDeleteAction/RestoreAction仅在已删除记录上显示,不要手动设置互相冲突的visible()/hidden()。 - 批量删除性能取舍:默认
deleteAny()授权 + 查询级删除是最快路径;authorizeIndividualRecords()会逐条授权与逐条删除,仅在需要严格行级权限时启用。 - 配合回收站筛选使用:
TrashedFilter的三态设计(含回收站 / 仅回收站 / 默认)与批量动作的显隐联动,是构建完整"回收站"体验的关键,详见 tables 包文档 与 表格动作文档。 - 测试验证:本仓库在 tests/src/Actions 目录下提供了
DeleteActionTest.php、DeleteBulkActionTest.php、ForceDeleteActionTest.php、RestoreActionTest.php等测试用例,可作为理解各 Action 行为边界与编写自身测试的参考。
通过本文的配置与源码分析,你可以为任何 Filament 资源快速落地完整的删除生命周期,并确保权限模型与 UI 行为严格一致。
【免费下载链接】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),仅供参考