开始
概述
资源是用来为 Eloquent 模型创建 CRUD 接口的静态类。它描述了管理员如何在应用内,使用表格和表单,与数据进行交互的。
新建资源
为 App\Models\Customer
模型新建资源:
php artisan make:filament-resource Customer
在 app/Filament/Resources
目录下将会生成一系列文件:
.
+-- CustomerResource.php
+-- CustomerResource
| +-- Pages
| | +-- CreateCustomer.php
| | +-- EditCustomer.php
| | +-- ListCustomers.php
新的资源类在 CustomerResource.php
中。
Pages
目录下的类用于自定义应用中和资源交互的页面。这些页面是全页 Livewire 组件,你可以根据需要自定义。
如果你创建的资源并没有在导航菜单中显示,很可能是因为你的模型策略的
viewAny()
方法并没有返回true
。
简易(模态框)资源
有时候,你的模型过于简单,因此你只想在单个页面中管理记录。这种情况下你可以使用模态框进行创建,编辑和删除记录。要生成这样一个带有模态框的简易资源:
php artisan make:filament-resource Customer --simple
你的资源有一个管理(Manage)页面,该页面是一个带有模态框的列表页。
另外,你的资源类不再会有 getRelations()
方法,因为关系管理器只会在编辑页和查看页中展示,不会出现在简易资源中。其他方面则与普通资源相同。
自动生成表单和表格
如果你要节约时间,Filament 也可以基于你模型数据库的字段,为你自动生成一些表单和表格,请使用 --generate
:
php artisan make:filament-resource Customer --generate
如果数据库表中含有 ENUM 字段,
doctrine/dbal
包将无法扫描表格且会崩溃。因此 Filament 无法据此为资源生成 schema。更多详情查阅此处。
处理软删除
默认情况下,你不能在应用中和已删除的记录进行交互。如果你想要在资源中添加恢复(restore)、强制删除和过滤垃圾记录等功能,可以在生成资源的时候使用 --soft-deletes
标志:
php artisan make:filament-resource Customer --soft-deletes
你点击此处查阅更多关于软删除功能。
生成查看页面
默认情况下,资源只会生成列表页,新建页和编辑页。如果你也想要生成查看页,请使用 --view
标志:
php artisan make:filament-resource Customer --view
指定自定义模型命名空间
默认情况下,Filament 会假定你的模型在 App\Models
目录中。你可以使用 --model-namspace
标志,传入不同的模型命名空间:
php artisan make:filament-resource Customer --model-namespace=Custom\\Path\\Models
本例中,模型在 Custom\Path\Models\Customer
。请注意命令行中要求使用双反斜杆 \\
。
生成资源时,Filament 将能够定位模型并读取数据库 schema。
记录标题
你可以为资源设置 $recordTitleAttribute
属性,该属性对应模型上的字段名,可以用于将其与其他模型区别开来。(译者:此处直译,意思是大体是在搜索时用以确认某条记录的唯一性。)
比如,它可以是博客文章的标题(title)
或者客户的名字(name)
:
protected static ?string $recordTitleAttribute = 'name';
此属性需要启用全局搜索特性才有效。
如果某个单一字段无法有效识别一条记录,你可以指定一个 Eloquent 获取器的名称。
资源表单
资源类中包含着一个 form()
方法,用于为新建和编辑页面创建表单:
use Filament\Forms;
use Filament\Forms\Form;
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('email')->email()->required(),
// ...
]);
}
schema()
方法用于定义表单结构。它是一个表单控件和布局组件数组,按照显示顺序在表单中排序。
关于如何使用 Filament 创建表单,请查阅表单文档向导。
基于当前操作中隐藏组件
表单组件的 hiddenOn()
方法让你可以基于当前页面或操作动态隐藏字段组件。
此例中,我们在 edit
编辑页面中隐藏了 password
字段:
use Livewire\Component;
Forms\Components\TextInput::make('password')
->password()
->required()
->hiddenOn('edit'),
此外,还有一个 visibleOn()
快捷方法,用来在页面或 Action 中显示字段:
use Livewire\Component;
Forms\Components\TextInput::make('password')
->password()
->required()
->visibleOn('create'),
资源表格
Resource 类包含一个静态 table()
方法,用以在列表页中创建表格:
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('email'),
// ...
])
->filters([
Tables\Filters\Filter::make('verified')
->query(fn (Builder $query): Builder => $query->whereNotNull('email_verified_at')),
// ...
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
请查阅表格构造器文档,了解如何添加表格列、过滤器、Action 等。
授权
关于授权,Filament 会监听所有应用中注册的模型策略。使用如下方法:
viewAny()
用于完全从导航菜单中隐藏资源,阻止用户访问任何页面。create()
用于控制新建记录。update()
用于控制编辑记录。view()
用于控制查看记录。delete()
用于阻止单条记录被删除。deleteAny()
用于防止记录被批量删除。Filament 使用deleteAny()
方法因为通过迭代检查delete()
策略性能不是很好。forceDelete()
用于防止单条软删除记录被强制删除。forceDeleteAny()
用于防止记录被批量强制删除。Filament 之所以使用forceDeleteAny()
因为在多条记录中迭代检查forceDelete()
策略性能不佳。restore()
用于防止单条软删除记录被强制恢复。restoreAny()
用于防止记录被批量强制删除。Filament 之所以使用restoreAny()
因为在多条记录中迭代检查restore()
策略性能不佳。reorder()
用于控制重新排序。
跳过授权
如果你想让某个资源跳过授权,可以将 $shouldSkipAuthorization
属性设置为 true
:
protected static bool $shouldSkipAuthorization = true;
自定义模型标签
每个资源都有一个基于模型名自动生成的"模型标签(model label)"。比如,App\Models\Customer
有一个 Customer
标签。
该标签用在 UI 的多个位置中,你可以使用 $modelLabel
属性对其进行自定义:
protected static ?string $modelLabel = 'cliente';
此外,你也可以使用 getModelLabel()
方法去定义动态标签:
public static function getModelLabel(): string
{
return __('filament/resources/customer.label');
}
自定义复数模型标签
资源同时有一个基于模型标签自动生成的"复数模型标签(plural model label)"。比如,customer
标签的复数是 customers
。
你可以使用 $pluralModelLabel
属性自定义标签的复数版本:
protected static ?string $pluralModelLabel = 'clientes';
此外,你可以在 getPluralModelLabel()
方法中设置动态复数标签:
public static function getPluralModelLabel(): string
{
return __('filament/resources/customer.plural_label');
}
模型标签自动大写
默认情况下,对于 UI 的某些部分,Filament 将自动将模型标签中的每个单词大写。例如,在页面标题、导航菜单和面包屑中。
如果你想在资源中禁用 该行为,你可以在资源中设置 $hasTitleCaseModelLabel
:
protected static bool $hasTitleCaseModelLabel = false;
资源导航项
Filament 会使用复数标签为资源自动生成导航菜单项。
如果你想自定义导航项标签,你可以使用 $navigationLabel
属性:
protected static ?string $navigationLabel = 'Mis Clientes';
此外,你可以在 getNavigationLabel()
设置为动态导航标签:
public static function getNavigationLabel(): string
{
return __('filament/resources/customer.navigation_label');
}
设置资源导航图标
$navigationIcon
属性支持任何 Blade 模板组件名。默认情况下,Filament 安装了 Heroicons。不过,你可以创建自定义图标组件或者安装其他图标库。
protected static ?string $navigationIcon = 'heroicon-o-user-group';
此外,你可以在 getNavigationIcon()
方法中设置动态导航图标:
use Illuminate\Contracts\Support\Htmlable;
public static function getNavigationIcon(): string | Htmlable | null
{
return 'heroicon-o-user-group';
}
资源导航项排序
$navigationSort
属性让你可以指定导航项的排列顺序:
protected static ?int $navigationSort = 2;
此外,在 getNavigationSort()
方法中你可以动态设置导航项排序:
public static function getNavigationSort(): ?int
{
return 2;
}
导航菜单分组
你可以通过 $navigationGroup
属性对导航菜单进行分组:
protected static ?string $navigationGroup = 'Shop';
此外,你也可以使用 getNavigationGroup()
方法设置动态分组标签:
public static function getNavigationGroup(): ?string
{
return __('filament/navigation.groups.shop');
}
将资源导航项分组到一个项目下
将父级项目的标签传入到 $navigationParentItem
,你可以将导航项作为其他项目的子项目进行分组:
protected static ?string $navigationParentItem = 'Products';
protected static ?string $navigationGroup = 'Shop';
如上所示,如果父级项目有一个导航分组,则必须定义该导航组,这样才能正确识别父级项目。
你也可以调用 $getNavigationParentItem()
方法,动态设置父级项目标签:
public static function getNavigationParentItem(): ?string
{
return __('filament/navigation.groups.shop.items.products');
}
为资源页生成 URL
Filament 在资源类中使用 getUrl()
静态方法,用来为资源和特定页面生成 URL。一般来说,你需要手动或使用 Laravel 的 route()
帮助函数来构建 URL,而这些方法依赖于对资源的 slug 或路由命名规范的了解。
不带任何参数的 getUrl()
方法,将会为资源列表页生成 URL:
use App\Filament\Resources\CustomerResource;
CustomerResource::getUrl(); // /admin/customers
你可以为资源中的指定页面生成 URL。每个页面的名字是资源 getPages()
数组中的数组键名。比如,要为新建页生成 URL:
use App\Filament\Resources\CustomerResource;
CustomerResource::getUrl('create'); // /admin/customers/create
getPages()
方法中的一些页面使用了 URL 参数[比如,record
]。要为这些页面生成 URL,并传入记录,你可以使用第二个参数:
use App\Filament\Resources\CustomerResource;
CustomerResource::getUrl('edit', ['record' => $customer]); // /admin/customers/edit/1
本例中,$customer
可以是一个 Eloquent 模型对象,或者 ID。
资源模态框生成 URL
如果您只在一个页面上使用简单资源,这将特别有用。
要为资源表中的 Action 生成 URL,应将 tableAction
和 tableActionRecord
作为 URL 参数传递:
use App\Filament\Resources\CustomerResource;
use Filament\Tables\Actions\EditAction;
CustomerResource::getUrl(parameters: [
'tableAction' => EditAction::getDefaultName(),
'tableActionRecord' => $customer,
]); // /admin/customers?tableAction=edit&tableActionRecord=1
或者如果你想为页面的 Action(如页面头部的 createAcion
) 生成 URL,你可以将其传到 action
参数中:
use App\Filament\Resources\CustomerResource;
use Filament\Actions\CreateAction;
CustomerResource::getUrl(parameters: [
'action' => CreateAction::getDefaultName(),
]); // /admin/customers?action=create
为其他面板中的资源生成 URL
如果你的应用中有多个面板,getUrl()
将会在当前面板生成一个 URL。你也可以传入面板给 panel
参数,说明该资源应该关联到哪个面板:
use App\Filament\Resources\CustomerResource;
CustomerResource::getUrl(panel: 'marketing');
自定义资源 Eloquent 查询
在 Filament 中,每个资源模型的查询都会从 getEloquentQuery()
方法开始。
因此,可以很容易使用你自己的查询约束或影响整个资源的模型范围(scope)查询:
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()->where('is_active', true);
}