资源
管理关联
选择合适的工具
Filament 提供了多种在应用中管理管理的方法。选择哪个方式取决于你管理的关联类型和你希望的 UI 界面。
关联管理器 - 资源表单下方的交互式表格
NOTE
该方式兼容 HasMany、HasManyThrough、BelongsToMany、MorphMany 和 MorphToMany 关联。
关联管理器是允许管理员在不离开资源的编辑页或查看页的情况下,列出、创建、编辑、删除、关联、取消关联、附加、分离关联记录的互动式表格。
Select & checkbox list - 从现有记录中选择或者创建新记录
NOTE
该方式兼容 BelongsTo、MorphTo 和 BelongsToMany 关联。
使用 Select,用户可以从已有记录清单中进行选择。你页可以添加一个允许用户在模态框中创建新纪录的按钮,而无需离开页面。
当在 Select 中使用 BelongsToMany 关联时,你可以选择多个选项。记录会在你提交表单时,自动添加到中间表中。你也可以使用 Checkbox List替换多选下拉框。这两个组件的工作原理相同。
Repeater - 在表单中 CRUD 多个关联纪律
NOTE
该方式兼容 HasMany 和 MorphMany 关联。
Repeater是标准的表单组件,可以无限渲染一组可重复的字段。它们可以钩入到关联中,因此记录会自动从相关表中读取、创建、更新和删除。它们位于主表单 Schema 中,可以在资源页面中使用,也可以在嵌套到操作模态框中。
就用户体验角度而言,该方案只适合于关联模型中只有少数几个字段。否则,表单可能会变得非常长。
布局表单组件 - 保存表单字段到单个关联中
NOTE
该方式兼容 BelongsTo、HasOne 和 MorphOne 关联。
所有布局表单组件(Grid、Section、Fieldset等)都由一个 relationship() 方法。当你使用这一方式,所有布局组件类的字段都将保存到关联模型而非所有者(owner)模型中:
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Fieldset;
Fieldset::make('Metadata')
->relationship('metadata')
->schema([
TextInput::make('title'),
Textarea::make('description'),
FileUpload::make('image'),
])
本例中,title、description 和 image 自动从 metadata 关联中自动加载,并且在表单提交时再次保存。如果该 metadata 记录不存在,它将自动创建。
该特性在表单文档由更详尽深入的解释。请访问了解更多如何使用的信息。
创建关联管理器
要创建关联管理器,你可以使用 make:filament-relation-manager 命令:
php artisan make:filament-relation-manager CategoryResource posts title
CategoryResource是所有者(父级)模型的资源类的名称。posts是你想要管理的关联的名称。title是你用以识别文章(post)的属性名。
这将创建一个 CategoryResource/RelationManagers/PostsRelationManager.php 文件。它包含一个你可以定义资源管理器的表单和表格的类:
use Filament\Forms;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Table;
public function form(Schema $schema): Schema
{
return $schema
->components([
Forms\Components\TextInput::make('title')->required(),
// ...
]);
}
public function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('title'),
// ...
]);
}
你必须在资源的 getRelations() 方法中注册新的关联管理器:
public static function getRelations(): array
{
return [
RelationManagers\PostsRelationManager::class,
];
}
当关联管理器定义了表格和表单后,请访问资源的编辑页或查看页,以查看其实际操作。
只读模式
关联管理器通常显示在资源的“编辑”或“查看”页面上。在“查看”页面上,Filament 将自动隐藏修改关联的所有操作,如创建、编辑和删除。我们称之为“只读模式”,默认情况下,它保留了“查看”页面的只读行为。但是,你可以通过重写关联管理器类上的 isReadOnly() 方法使之始终返回 false 来禁用此行为:
public function isReadOnly(): bool
{
return false;
}
此外,如果你不喜欢该功能,你可以在面板配置中一次性禁用所有关联管理器的只读模式:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->readOnlyRelationManagersOnResourceViewPagesByDefault(false);
}
非常规的反转关联名
对于未遵循 Laravel 命名规范的反转关联,你可以在表格上使用 inverseRelationship() 方法:
use Filament\Tables;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('title'),
// ...
])
->inverseRelationship('section'); // Since the inverse related model is `Category`, this is normally `category`, not `section`.
}
处理软删除
默认情况下,你将无法在关联管理器中与已删除的记录进行交互。如果你想在关联管理器中添加恢复、强制删除和过滤垃圾记录的功能,请在生成关联管理器时使用 --soft deletes 标志:
php artisan make:filament-relation-manager CategoryResource posts title --soft-deletes
你可以在此处查阅更多软删除的信息。
列出关联记录
关联记录会在表格中列出。整个关联管理器都是基于此表格,包含创建、编辑、附加/分离、关联/取消关联和删除记录的操作。
你可以使用表格构造器的所有特性来自定义关联管理器。
使用中间表属性罗列
对于 BelongsToMany 和 MorphToMany 关联,你也可以添加中间表属性。比如你的 UserResource 资源有一个 TeamsRelationManager 关联,你想要添加 role 中间表属性到该表格,你可以使用:
use Filament\Tables;
public function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('role'),
]);
}
请确保所有的中间表属性都在关联及反转关联的 withPivot() 方法中列出。
创建关联记录
使用中间表属性创建关联
对于 BelongsToMany 和 MorphToMany 关联,你也可以添加中间表属性。比如你的 UserResource 资源有一个 TeamsRelationManager 关联,你想要添加 role 中间表属性到新建表单中,你可以使用:
use Filament\Forms;
use Filament\Schemas\Schema;
public function form(Schema $schema): Schema
{
return $schema
->components([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('role')->required(),
// ...
]);
}
请确保所有的中间表属性都在关联及反转关联的 withPivot() 方法中列出
自定义 CreateAction
要了解如何自定义 CreateAction,包括操纵单数据、修改通知以及添加生命周期钩子,请查阅 Action 文档。
编辑关联记录
使用中间表属性编辑
对于 BelongsToMany 和 MorphToMany 关联,你也可以添加中间表属性。比如你的 UserResource 资源有一个 TeamsRelationManager 关联,你想要添加 role 中间表属性到编辑表单中,你可以使用:
use Filament\Forms;
use Filament\Schemas\Schema;
public function form(Schema $schema): Schema
{
return $schema
->components([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('role')->required(),
// ...
]);
}
请确保所有的中间表属性都在关联及反转关联的 withPivot() 方法中列出。
自定义 EditAction
要了解如何自定义 EditAction,包括操纵单数据、修改通知以及添加生命周期钩子,请查阅 Action 文档。
附加和分离记录
Filament 可以为 BelongsToMany 和 MorphToMany 关联附加和分离记录。
生成关联管理器时,你可以传入 --attach 标志,以同时添加 AttachAction、DetachAction 和 DetachBulkAction 操作到表格中:
php artisan make:filament-relation-manager CategoryResource posts title --attach
另外,如果你已经生成了资源,你可以只添加这些操作到 $table 中:
use Filament\Actions\AttachAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DetachAction;
use Filament\Actions\DetachBulkAction;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->columns([
// ...
])
->headerActions([
// ...
AttachAction::make(),
])
->recordActions([
// ...
DetachAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
// ...
DetachBulkAction::make(),
]),
]);
}
预加载附加模态框选择选项
默认情况下,当你搜索要附加的记录时,选项将通过 AJAX 从数据库加载。如果你希望在表单首次加载时预加载这些选项,可以使用 AttachAction 的 preloadRecordSelect() 方法:
use Filament\Actions\AttachAction;
AttachAction::make()
->preloadRecordSelect()
附加中间属性
当你使用 Attach 附加按钮附加记录时,你可能希望定义一个自定义表单来将中间表属性添加到关联中:
use Filament\Actions\AttachAction;
use Filament\Forms;
AttachAction::make()
->form(fn (AttachAction $action): array => [
$action->getRecordSelect(),
Forms\Components\TextInput::make('role')->required(),
])
此例中,$action->getRecordSelect() 返回 Select 字段以选择要附加的记录。然后,role 文本输入框将保存到中间表的 role 列中。
请确保所有的中间表属性都在关联及反转关联的 withPivot() 方法中列出
限定附加的选项查询范围:
你可能想要对 AttachAction 的选项限定查询范围:
use Filament\Actions\AttachAction;
use Illuminate\Database\Eloquent\Builder;
AttachAction::make()
->recordSelectOptionsQuery(fn (Builder $query) => $query->whereBelongsTo(auth()->user()))
跨越多列搜索要附加的选项
默认情况下,要附加的 AttachAction 的选项会在表格的 recordTitleAttribute() 中进行搜索。如果你希望搜索多个字段,可以使用 recordSelectSearchColumns() 方法:
use Filament\Actions\AttachAction;
AttachAction::make()
->recordSelectSearchColumns(['title', 'description'])
附加多个记录
AttachAction 组件的 multiple() 方法允许你选择多个值:
use Filament\Actions\AttachAction;
AttachAction::make()
->multiple()
自定义附加模态框中的 Select 字段
你可以通过将函数传递给 recordSelect() 方法来自定义附加过程中使用的 Select 字段对象:
use Filament\Actions\AttachAction;
use Filament\Forms\Components\Select;
AttachAction::make()
->recordSelect(
fn (Select $select) => $select->placeholder('Select a post'),
)
处理重复项
默认情况下,你不允许多次附加同一条记录。这是因为你必须在中间表上设置一个主键 id 列才能使此功能生效。
请确保 id 属性在关联 和 反向关联的 withPivot() 方法中列出。
最后,请将 allowDuplicates() 方法添加到表中:
public function table(Table $table): Table
{
return $table
->allowDuplicates();
}
提升批量分离操作的性能
默认情况下,DetachBulkAction 会将所有 Eloquent 记录加载到内存中,然后循环遍历并逐条分离。
如果你要分离大量记录,建议你使用 chunkSelectedRecords() 方法一次性提取少量记录。这将减少应用的内存占用:
use Filament\Actions\DetachBulkAction;
DetachBulkAction::make()
->chunkSelectedRecords(250)
Filament 在分离 Eloquent 记录之前会将其加载到内存中,原因有二:
- 允许在分离之前使用模型策略对集合中的单个记录进行授权(比如,使用
authorizeIndividualRecords('delete'))。 - 确保在分离记录时运行模型事件,例如模型观察器中的
deleting和deleted事件。
如果你不需要单个记录策略授权和模型事件,你可以使用 fetchSelectedRecords(false) 方法,该方法不会在分离记录之前将记录加载到内存中,而是在单个查询中分离它们:
use Filament\Actions\DetachBulkAction;
DetachBulkAction::make()
->fetchSelectedRecords(false)
关联和解除关联记录
Filament 能够关联和解除关联 HasMany 和 MorphMany 关系的记录。
生成关联管理器时,你可以传递 --associate 标志,以便将 AssociateAction、DissociateAction 和 DissociateBulkAction 添加到表中:
php artisan make:filament-relation-manager CategoryResource posts title --associate
或者,如果你已经生成了资源,则只需将操作(Action)添加到 $table 数组中:
use Filament\Actions\AssociateAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DissociateAction;
use Filament\Actions\DissociateBulkAction;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->columns([
// ...
])
->headerActions([
// ...
AssociateAction::make(),
])
->recordActions([
// ...
DissociateAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
// ...
DissociateBulkAction::make(),
]),
]);
}
预加载关联模态框 Select 选项
默认情况下,当你索要关联的记录时,选项将通过 AJAX 从数据库加载。如果你希望在表单首次加载时预加载这些选项,可以使用 AssociateAction 的 preloadRecordSelect() 方法:
use Filament\Actions\AssociateAction;
AssociateAction::make()
->preloadRecordSelect()
限定关联选项查询范围:
你可能想要对 AssociateAction 的选项限定查询范围:
use Filament\Actions\AssociateAction;
use Illuminate\Database\Eloquent\Builder;
AssociateAction::make()
->recordSelectOptionsQuery(fn (Builder $query) => $query->whereBelongsTo(auth()->user()))
搜索选项跨列关联
默认情况下,AssociateAction 可用的选项将在表格的 recordTitleAttribute() 中搜索。如果你希望跨多列搜索,可以使用 recordSelectSearchColumns() 方法:
use Filament\Actions\AssociateAction;
AssociateAction::make()
->recordSelectSearchColumns(['title', 'description'])
关联多个记录
AssociateAction 组件上的 multiple() 方法允许你选择多个值:
use Filament\Actions\AssociateAction;
AssociateAction::make()
->multiple()
自定义关联模态框中的 Select 字段
你可以通过将函数传递给 recordSelect() 方法来自定义关联过程中使用的 Select 字段对象:
use Filament\Actions\AssociateAction;
use Filament\Forms\Components\Select;
AssociateAction::make()
->recordSelect(
fn (Select $select) => $select->placeholder('Select a post'),
)
、、、
提升批量解除关联操作的性能
默认情况下,DissociateBulkAction 会将所有 Eloquent 记录加载到内存中,然后循环遍历并逐一解除关联。
如果你要解除大量记录,建议使用 chunkSelectedRecords() 方法一次性获取较少数量的记录。这将减少应用的内存占用:
use Filament\Actions\DissociateBulkAction;
DissociateBulkAction::make()
->chunkSelectedRecords(250)
Filament 在解除关联之前会将 Eloquent 记录加载到内存中,原因有二:
- 允许在解除关联之前使用模型策略对集合中的单个记录进行授权(例如,使用
authorizeIndividualRecords('update'))。 - 确保在解除关联记录时运行模型事件,例如模型观察器中的
updating和updated事件。
如果你不需要单个记录策略授权和模型事件,可以使用 fetchSelectedRecords(false) 方法,该方法不会在解除关联之前将记录加载到内存中,而是在单个查询中解除关联:
use Filament\Actions\DissociateBulkAction;
DissociateBulkAction::make()
->fetchSelectedRecords(false)
查看关联记录
生成关联管理器时,你可以传递 --view 标志来向表格中添加 ViewAction:
php artisan make:filament-relation-manager CategoryResource posts title --view
或者,如果你已经生成了关联管理器,则只需将 ViewAction 添加到 $table->recordActions() 数组中:
use Filament\Actions\ViewAction;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->columns([
// ...
])
->recordActions([
ViewAction::make(),
// ...
]);
}
删除关联记录
默认情况下,你将无法在关联管理器中与已删除的记录进行交互。如果你想在关联管理器中添加恢复、强制删除和过滤已删除记录的功能,请在生成关联管理器时使用 --soft-deletes 标志:
php artisan make:filament-relation-manager CategoryResource posts title --soft-deletes
或者,你也可以添加软删除功能到现有的关联管理器中:
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 function table(Table $table): Table
{
return $table
->modifyQueryUsing(fn (Builder $query) => $query->withoutGlobalScopes([
SoftDeletingScope::class,
]))
->columns([
// ...
])
->filters([
TrashedFilter::make(),
// ...
])
->recordActions([
DeleteAction::make(),
ForceDeleteAction::make(),
RestoreAction::make(),
// ...
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
ForceDeleteBulkAction::make(),
RestoreBulkAction::make(),
// ...
]),
]);
}
自定义 DeleteAction
要了解如何自定义 DeleteAction,包括修改通知和添加生命周期钩子,请查看 Action 文档。
导入关联记录
可以将 ImportAction 添加到关联管理器的标题中,以导入记录。在这种情况下,你可能需要告知导入器这些新记录属于哪个所有者。你可以使用 导入选项 传递所有者记录的 ID:
ImportAction::make()
->importer(ProductImporter::class)
->options(['categoryId' => $this->getOwnerRecord()->getKey()])
现在,在导入器类中,你可以将所有者与导入的记录建立一对多关联:
public function resolveRecord(): ?Product
{
$product = Product::firstOrNew([
'sku' => $this->data['sku'],
]);
$product->category()->associate($this->options['categoryId']);
return $product;
}
或者,你可以使用导入器的 afterSave() 钩子将记录附加到多对多关联中:
protected function afterSave(): void
{
$this->record->categories()->syncWithoutDetaching([$this->options['categoryId']]);
}
访问关联的所有者记录
关联管理器是 Livewire 组件。首次加载时,所有者记录(作为父级的 Eloquent 记录 - 主资源模型)会保存到一个属性中。你可以使用以下方式读取此属性:
$this->getOwnerRecord()
不过,如果你在 static 静态方法(比如,form() 或者 table())中,$this 无法访问。因此,你可能会使用回调来访问 $livewire 实例:
use Filament\Forms;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Schemas\Schema;
public function form(Schema $schema): Schema
{
return $schema
->components([
Forms\Components\Select::make('store_id')
->options(function (RelationManager $livewire): array {
return $livewire->getOwnerRecord()->stores()
->pluck('name', 'id')
->toArray();
}),
// ...
]);
}
Filament 中的所有方法都接受回调,在其中你可以访问 $livewire->ownerRecord。
关联管理器分组
你可以将所有关联管理器分组到一个标签页中。为此,你可以使用标签将多个管理器包装到一个 RelationGroup 对象中:
use Filament\Resources\RelationManagers\RelationGroup;
public static function getRelations(): array
{
return [
// ...
RelationGroup::make('Contacts', [
RelationManagers\IndividualsRelationManager::class,
RelationManagers\OrganizationsRelationManager::class,
]),
// ...
];
}
条件性显示关联管理器
默认情况下,如果相关模型策略的 viewAny() 方法返回 true,则关联管理器将为可见。
你可以使用 canViewForRecord() 方法来确定关联管理器是否应对特定所有者记录和页面可见:
use Illuminate\Database\Eloquent\Model;
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
{
return $ownerRecord->status === Status::Draft;
}
将关联管理器选项卡与表单合并
在编辑或查看页面类中,重写 hasCombinedRelationManagerTabsWithContent() 方法:
public function hasCombinedRelationManagerTabsWithContent(): bool
{
return true;
}
自定义内容标签页
在编辑或查看页面类中,重写 getContentTabComponent() 方法,并使用任何 Tab 自定义方法:
use Filament\Schemas\Components\Tabs\Tab;
public function getContentTabComponent(): Tab
{
return Tab::make('Settings')
->icon('heroicon-m-cog');
}
设置表单标签页位置
默认情况下,表单选项卡会在关联选项卡之前渲染。如果要在关联选项卡之后渲染,你可以重写编辑或查看页面类中的 getContentTabPosition() 方法:
use Filament\Resources\Pages\Enums\ContentTabPosition;
public function getContentTabPosition(): ?ContentTabPosition
{
return ContentTabPosition::After;
}
自定义关联管理器标签页
要自定义关联管理器的标签页,请重写 getTabComponent() 方法,并使用 [Tab(../schemas/tabs)] 的自定义方法:
use Filament\Schemas\Components\Tabs\Tab;
use Illuminate\Database\Eloquent\Model;
public static function getTabComponent(Model $ownerRecord, string $pageClass): Tab
{
return Tab::make('Blog posts')
->badge($ownerRecord->posts()->count())
->badgeColor('info')
->badgeTooltip('The number of posts in this category')
->icon('heroicon-m-document-text');
}
如果你正在使用关联分组,你可以使用 tab() 方法:
use Filament\Resources\RelationManagers\RelationGroup;
use Filament\Schemas\Components\Tabs\Tab;
use Illuminate\Database\Eloquent\Model;
RelationGroup::make('Contacts', [
// ...
])
->tab(fn (Model $ownerRecord): Tab => Tab::make('Blog posts')
->badge($ownerRecord->posts()->count())
->badgeColor('info')
->badgeTooltip('The number of posts in this category')
->icon('heroicon-m-document-text'));
与关联管理器共享资源的表单和表格
你可能希望资源的表单和表格与关联管理器的完全相同,并希望重用之前编写的代码。这很简单,只需从关联管理器中调用资源的 form() 和 table() 方法即可:
use App\Filament\Resources\Blog\Posts\PostResource;
use Filament\Schemas\Schema;
use Filament\Tables\Table;
public function form(Schema $schema): Schema
{
return PostResource::form($schema);
}
public function table(Table $table): Table
{
return PostResource::table($table);
}
隐藏关联管理器上的共享表单组件
如果你要与关联管理器共享资源中的表单组件,你可能需要在关联管理器上隐藏它。如果你想在关联管理器中隐藏所有者记录的 Select 字段,此功能尤其有用,因为 Filament 无论如何都会为你处理此问题。为此,你可以使用 hiddenOn() 方法,并传递关联管理器的名称:
use App\Filament\Resources\Blog\Posts\PostResource\RelationManagers\CommentsRelationManager;
use Filament\Forms\Components\Select;
Select::make('post_id')
->relationship('post', 'title')
->hiddenOn(CommentsRelationManager::class)
隐藏关联管理器的共享表格列
如果你与关联管理器共享资源中的某个表格列,你可能需要在关联管理器中隐藏该列。如果你想在关联管理器中隐藏所有者记录的那一列,则此功能尤其有用,因为当所有者记录已在关联管理器上方列出时,显示该列并不合适。为此,你可以使用 hiddenOn() 方法,并传递关联管理器的名称:
use App\Filament\Resources\Blog\Posts\PostResource\RelationManagers\CommentsRelationManager;
use Filament\Tables\Columns\TextColumn;
TextColumn::make('post.title')
->hiddenOn(CommentsRelationManager::class)
隐藏关联管理器的共享表格过滤器
如果你与关联管理器共享资源中的某个表格过滤器,你可能需要在关联管理器上隐藏它。如果你想在关联管理器中隐藏所有者记录的过滤器,这尤其有用,因为表格已被所有者记录过滤时,显示该过滤器便不合适。为此,你可以使用 hiddenOn() 方法,并传递关联管理器的名称:
use App\Filament\Resources\Blog\Posts\PostResource\RelationManagers\CommentsRelationManager;
use Filament\Tables\Filters\SelectFilter;
SelectFilter::make('post')
->relationship('post', 'title')
->hiddenOn(CommentsRelationManager::class)
重写关联管理器上的共享配置
你在资源内部进行的任何配置都可以在关联管理器上被重写。例如,如果你想禁用关联管理器继承表上的分页功能,但不禁用资源本身的分页功能:
use App\Filament\Resources\Blog\Posts\PostResource;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return PostResource::table($table)
->paginated(false);
}
如果你想在关联管理器中为 创建、附加 或 关联 记录添加 Header 操作,那么在关联管理器上提供额外的配置可能也很有用:
use App\Filament\Resources\Blog\Posts\PostResource;
use Filament\Actions\AttachAction;
use Filament\Actions\CreateAction;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return PostResource::table($table)
->headerActions([
CreateAction::make(),
AttachAction::make(),
]);
}
自定义关联管理器的 Eloquent 查询
你可以应用自己的查询约束或模型查询范围,它们会影响整个关联管理器。为此,你可以将一个函数传递给表格的 modifyQueryUsing() 方法,在其中你可以自定义查询:
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
public function table(Table $table): Table
{
return $table
->modifyQueryUsing(fn (Builder $query) => $query->where('is_active', true))
->columns([
// ...
]);
}
自定义关联管理器标题
要设置关联管理器的标题,你可以使用关联管理器类上的 $title 属性:
protected static ?string $title = 'Posts';
要动态设置关联管理器的标题,你可以重写关联管理器类的 getTitle() 方法:
use Illuminate\Database\Eloquent\Model;
public static function getTitle(Model $ownerRecord, string $pageClass): string
{
return __('relation-managers.posts.title');
}
标题将反映在表格标题中,以及关联管理器选项卡(如果有多个)中。如果你想单独自定义表格标题,仍然可以使用 $table->heading() 方法:
use Filament\Tables;
public function table(Table $table): Table
{
return $table
->heading('Posts')
->columns([
// ...
]);
}
自定义管理管理器的记录标题
关联管理器使用“记录标题属性”的概念来确定应该使用相关模型的哪个属性来标识它。创建关联管理器时,此属性将作为 make:filament-relation-manager 命令的第三个参数传递:
php artisan make:filament-relation-manager CategoryResource posts title
上例中,Post 的 title 属性用于识别关联管理器的贴文(Post)。
这主要由 Action 类使用。例如,当你附加或关联一条记录时,其标题将列在选择字段中。当你编辑、查看或删除一条记录时,标题将用于模态框的标题中。
在某些情况下,你可能需要将多个属性连接在一起形成一个标题。你可以将 recordTitleAttribute() 配置方法替换为 recordTitle(),并传递一个将模型转换为标题的函数:
use App\Models\Post;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->recordTitle(fn (Post $record): string => "{$record->title} ({$record->id})")
->columns([
// ...
]);
}
如果你正在使用 recordTitle(),并且有一个 关联操作 或 附加操作,你还需要为这些操作指定搜索列:
use Filament\Actions\AssociateAction;
use Filament\Actions\AttachAction;
AssociateAction::make()
->recordSelectSearchColumns(['title', 'id']);
AttachAction::make()
->recordSelectSearchColumns(['title', 'id'])
关联页面
如果你希望将管理关联的功能与编辑或查看所有者记录的功能分离,那么使用 ManageRelatedRecords 页面是使用关联管理器的另一种选择。
如果你正在使用资源子导航,此功能非常适合,因为你可以轻松地在“查看”或“编辑”页面和关联页面之间切换。
要创建关联页面,你应该使用 make:filament-page 命令:
php artisan make:filament-page ManageCustomerAddresses --resource=CustomerResource --type=ManageRelatedRecords
运行此命令时,系统会询问你一系列问题以自定义页面,比如,关联的名称及其标题属性。
你必须在资源的 getPages() 方法中注册此新页面:
public static function getPages(): array
{
return [
'index' => Pages\ListCustomers::route('/'),
'create' => Pages\CreateCustomer::route('/create'),
'view' => Pages\ViewCustomer::route('/{record}'),
'edit' => Pages\EditCustomer::route('/{record}/edit'),
'addresses' => Pages\ManageCustomerAddresses::route('/{record}/addresses'),
];
}
NOTE
当使用关联页面时,你不需要使用 make:filament-relation-manager 生成关联管理器,你无需在资源的 getRelations() 方法中注册它。
现在,你可以按照与关联管理器完全相同的方式使用相同的 table() 和 form() 来自定义页面。
添加关联页面到资源子导航
如果你正在使用资源子导航,你可以在资源的 getRecordSubNavigation() 中正常注册此页面:
use App\Filament\Resources\Customers\Pages;
use Filament\Resources\Pages\Page;
public static function getRecordSubNavigation(Page $page): array
{
return $page->generateNavigationItems([
// ...
Pages\ManageCustomerAddresses::class,
]);
}
传递属性到关联管理器
当在资源中注册资源管理器时,你可以使用 make() 方法传入一个 Livewire 属性数组到其中:
use App\Filament\Resources\Blog\Posts\PostResource\RelationManagers\CommentsRelationManager;
public static function getRelations(): array
{
return [
CommentsRelationManager::make([
'status' => 'approved',
]),
];
}
该属性数组映射到资源管理器类的 public Livewire 属性:
use Filament\Resources\RelationManagers\RelationManager;
class CommentsRelationManager extends RelationManager
{
public string $status;
// ...
}
现在,你可以在资源管理器类中使用 $this->status 访问 $status:
禁用懒加载
默认情况下,关联管理器是延迟加载的。也就是说,只有当其在页面中可见时才会加载。
要禁用此行为,可用重写关联管理器类的 $isLazy 属性:
protected static bool $isLazy = false;
Edit on GitHubStill need help? Join our Discord community or open a GitHub discussion