关联管理器
开始
在 Filament 中,“关联管理器(Relation managers)” 允许管理员可以在不离开资源编辑页面的情况下,展示列表、新建、编辑、删除、附加和取消附加、关联和取消关联相关记录。资源类包含了一个静态的 getRelations() 方法,用于为资源注册关联管理器。
要新建关联管理器,你可以使用 make:filament-relation-manager 命令:
php artisan make:filament-relation-manager CategoryResource posts title
CategoryResource是对应父级模型的资源类名。posts是你想要管理的关联名。title是用来识别 posts 唯一性的属性名。
这个命令将会创建 CategoryResource/RelationManagers/PostsRelationManager.php 文件。它包含了一个类,让你可以为你的关联管理器定义表单和表格:
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Table;
use Filament\Tables;
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('title')->required(),
Forms\Components\MarkdownEditor::make('content'),
// ...
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('title'),
// ...
]);
}
你必须在资源的 getRelations() 方法中注册这些新的模型关联管理器:
public static function getRelations(): array
{
return [
RelationManagers\PostsRelationManager::class,
];
}
对于使用非常规命名规范的关联,你可以在关联管理器中使用 $inverseRelationship 属性中:
protected static ?string $inverseRelationship = 'section'; // 反转关联的模型是 `Category`,所以一般情况下这里是 `category` 而非 `section`。
如果关联管理器中定义了表格和表单,可以通过操作(Action)访问编辑页或者查看页。
处理软删除
默认情况下,你不能在关联管理器中和已删除的数据进行交互。如果你想要在关联管理器中添加恢复数据、强制删除和过滤垃圾数据等功能,可以在生成关联管理器的时候使用 --soft-deletes 标志:
php artisan make:filament-relation-manager CategoryResource posts title --soft-deletes
记录列表
相关记录会在一个表格中展示。整个关联管理器都是基于这个表格,包括新建、编辑、附加/分离记录、关联/取消关联和删除记录等操作。
按照列表页中的文档,你可以在关联管理器类中使用所有的自定义功能:
此外,你页可以使用表格构造器的其他所有特性。
使用中间属性展示列表
对于 BelongsToMany 和 MorphToMany 关联(relationship),你也可以添加中间表属性。比如,如果你的资源 UserResource 有一个关联管理器 TeamsRelationManager,而且你想要将 role 中间属性添加到表格,你可以:
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Tables;
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('role'),
]);
}
请确保所有的中间属性都在关联和反向关联的 withPivot() 方法中罗列出来。
创建记录
使用中间属性新建记录
对于 BelongsToMany 和 MorphToMany 关联(relationship),你也可以 添加中间表属性。比如,如果你的资源 UserResource 有一个关联管理器 TeamsRelationManager,你想要在新建表单中添加关联属性,你可以:
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Tables;
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('role')->required(),
// ...
]);
}
请确保所有的中间属性都在关联和反向关联的 withPivot() 方法中罗列出来。
保存前自定义数据
有时,你可能需要在最终存入数据库前修改表单数据。此时可以使用 mutateFromDataUsing() 方法,该方法接收一个 $data 数组,返回修改后的数据:
use Filament\Tables\Actions\CreateAction;
CreateAction::make()
->mutateFormDataUsing(function (array $data): array {
$data['user_id'] = auth()->id();
return $data;
})
自定义新建处理过程
你可以使用 process() 方法微调记录的创建过程:
use Filament\Tables\Actions\CreateAction;
use Illuminate\Database\Eloquent\Model;
CreateAction::make()
->process(function (array $data): Model {
return static::getModel()::create($data);
})
自定义保存通知
当记录成功创建,会发送通知给用户,告知操作成功。
要自定义通知内容:
use Filament\Tables\Actions\CreateAction;
CreateAction::make()
->successNotificationTitle('User registered')
要完全禁用通知:
use Filament\Tables\Actions\CreateAction;
CreateAction::make()
->successNotification(null)
生命周期钩子
钩子可用于操作生命周期的各个结点中执行代码。
use Filament\Tables\Actions\CreateAction;
CreateAction::make()
->beforeFormFilled(function () {
// Runs before the form fields are populated with their default values.
})
->afterFormFilled(function () {
// Runs after the form fields are populated with their default values.
})
->beforeFormValidated(function () {
// Runs before the form fields are validated when the form is submitted.
})
->afterFormValidated(function () {
// Runs after the form fields are validated when the form is submitted.
})
->before(function () {
// Runs before the form fields are saved to the database.
})
->after(function () {
// Runs after the form fields are saved to the database.
})
停止新建处理过程
你可以随时在生命周期钩子内或者 mutation 方法内调用 $this->halt(), 停止整个新建处理过程:
use Filament\Notifications\Actions\Action;
use Filament\Notifications\Notification;
use Filament\Tables\Actions\CreateAction;
CreateAction::make()
->before(function (CreateAction $action) {
if (! $this->ownerRecord->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() 取消所有操作,而不必 halt():
$action->cancel();