管理关联
选择合适的工具
Filament 提供多种方式管理应用中的关联。应使用哪种功能,取决于你管理的关联类型,以及期望的 UI。
关联管理器 - 资源表单下方的交互式表格
INFO
兼容 HasMany、HasManyThrough、BelongsToMany、MorphMany 与 MorphToMany 关联。
关联管理器 是交互式表格,允许管理员在不离开资源编辑页或查看页的情况下,列出、创建、附加、关联、编辑、分离、解除关联并删除相关记录。
选择器与复选框列表 - 从现有记录中选择或新建
INFO
兼容 BelongsTo、MorphTo 与 BelongsToMany 关联。
使用 选择器,用户可从现有记录列表中选择。也可 添加按钮,在模态中创建新记录,而无需离开页面。
在 BelongsToMany 关联上使用选择器时,可选择多个选项,而不只是一个。提交表单时记录会自动加入中间表。若愿意,可将多选下拉替换为简单的 复选框列表。两种组件工作方式相同。
重复器 - 在所有者表单内对多条相关记录做 CRUD
INFO
兼容 HasMany 与 MorphMany 关联。
重复器 是标准表单组件,可无限渲染可重复的字段组。它们可挂接到关联,从而自动从相关表读取、创建、更新与删除记录。它们位于主表单 schema 内,可用于资源页面,也可嵌套在操作模态中。
从 UX 角度看,仅当相关模型字段较少时才适合此方案,否则表单会变得很长。
布局表单组件 - 将表单字段保存到单个关联
INFO
兼容 BelongsTo、HasOne 与 MorphOne 关联。
所有布局表单组件(Grid、Section、Fieldset 等)都有 relationship() 方法。使用后,该布局内的所有字段会保存到相关模型,而不是所有者模型:
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 记录不存在,会自动创建。
此功能在 Forms 文档 中有更深入说明。请访问该页了解用法。
创建关联管理器
要创建关联管理器,可使用 make:filament-relation-manager 命令:
php artisan make:filament-relation-manager CategoryResource posts titleCategoryResource是所有者(父)模型的资源类名。posts是要管理的关联名称。title是用于标识 posts 的属性名。
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,
];
}

自定义关联管理器的 URL 参数
若向 getRelations() 返回的数组传入键,切换多个关联管理器时会在 URL 中使用该键。例如,可传入 posts,使 URL 使用 ?relation=posts 而非数字数组索引:
public static function getRelations(): array
{
return [
'posts' => 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,包括变更表单数据、更改通知以及添加生命周期钩子,请参阅 操作文档。
编辑相关记录
编辑时带中间表属性
对于 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,包括变更表单数据、更改通知以及添加生命周期钩子,请参阅 操作文档。
附加与分离记录
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(),
]),
]);
}

DANGER
AssociateAction、AttachAction、DetachAction 与 DissociateAction(及其批量变体)仅检查关联管理器的 isReadOnly() 状态——默认不会查阅任何模型策略方法。批量删除、强制删除与恢复操作会使用 deleteAny()、forceDeleteAny() 与 restoreAny() 策略方法(整批一次调用)以兼顾性能。若需要在批量操作上做逐条授权,请对其调用 authorizeIndividualRecords('ability'),并接受额外的查询开销。
预加载附加模态的选择选项
默认情况下,搜索要附加的记录时,选项会通过 AJAX 从数据库加载。若希望在表单首次加载时预加载这些选项,可使用 AttachAction 的 preloadRecordSelect() 方法:
use Filament\Actions\AttachAction;
AttachAction::make()
->preloadRecordSelect()附加时带中间表属性
用 Attach 按钮附加记录时,你可能希望定义自定义表单,为关联添加中间表属性:
use Filament\Actions\AttachAction;
use Filament\Forms;
AttachAction::make()
->schema(fn (AttachAction $action): array => [
$action->getRecordSelect(),
Forms\Components\TextInput::make('role')->required(),
])在此例中,$action->getRecordSelect() 返回用于选择要附加记录的选择字段。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()自定义附加模态中的选择字段
可通过向 recordSelect() 方法传入函数,自定义附加过程中使用的选择字段对象:
use Filament\Actions\AttachAction;
use Filament\Forms\Components\Select;
AttachAction::make()
->recordSelect(
fn (Select $select) => $select->placeholder('Select a post'),
)用模态表格选择要附加的记录
可使用 tableSelect() 方法,在附加模态中用完整的 Filament 表格选择记录,而不是简单的选择下拉:
use App\Filament\Resources\Products\Tables\ProductsTable;
use Filament\Actions\AttachAction;
AttachAction::make()
->tableSelect(ProductsTable::class)在此例中,ProductsTable 是标准的 Filament 表格类,其 configure() 方法定义表格的列:
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
public static function configure(Table $table): Table
{
return $table
->columns([
TextColumn::make('name'),
TextColumn::make('sku'),
// ...
])
->filters([
// ...
]);
}DANGER
筛选表格查询(通过 modifyQueryUsing()、筛选器或表格参数)是展示性的——它只影响显示哪些记录供选择。它不是安全边界:篡改提交的模态状态的用户,仍可能附加未出现在可见表格中的记录。
要限制实际可附加的记录,请用 recordSelectOptionsQuery() 方法 限定选项。Filament 会按该查询解析提交的记录,因此查询之外的记录会被拒绝:
use App\Filament\Resources\Products\Tables\ProductsTable;
use Filament\Actions\AttachAction;
use Illuminate\Database\Eloquent\Builder;
AttachAction::make()
->tableSelect(ProductsTable::class)
->recordSelectOptionsQuery(fn (Builder $query) => $query->whereBelongsTo(auth()->user()))处理重复
默认情况下,不允许多次附加同一条记录。因为要使此功能生效,还必须在中间表上设置主键 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或者,若已生成资源,只需将这些操作加入 $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(),
]),
]);
}预加载关联模态的选择选项
默认情况下,搜索要关联的记录时,选项会通过 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()自定义关联模态中的选择字段
可通过向 recordSelect() 方法传入函数,自定义关联过程中使用的选择字段对象:
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,包括更改通知以及添加生命周期钩子,请参阅 操作文档。
导入相关记录
可将 ImportAction 添加到关联管理器的页眉以导入记录。此时,你可能希望告知 importer 这些新记录属于哪个所有者。可用 导入选项 传入所有者记录的 ID:
ImportAction::make()
->importer(ProductImporter::class)
->options(['categoryId' => $this->getOwnerRecord()->getKey()])现在,在 importer 类中,可将所有者与导入记录建立一对多关联:
public function resolveRecord(): ?Product
{
$product = Product::firstOrNew([
'sku' => $this->data['sku'],
]);
$product->category()->associate($this->options['categoryId']);
return $product;
}或者,可用 importer 的 afterSave() 钩子,在多对多关联中附加记录:
protected function afterSave(): void
{
$this->record->categories()->syncWithoutDetaching([$this->options['categoryId']]);
}访问关联的所有者记录
关联管理器是 Livewire 组件。首次加载时,所有者记录(作为父级的 Eloquent 记录——主资源模型)会保存到一个属性中。可读该属性:
$this->getOwnerRecord()不过,若在 form() 或 table() 等 static 方法中,无法访问 $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('Interactions', [
RelationManagers\CommentsRelationManager::class,
RelationManagers\TagsRelationManager::class,
]),
RelationGroup::make('Links', [
RelationManagers\LinksRelationManager::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 自定义方法:
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');
}TIP
除静态值外,badgeColor() 与 badgeTooltip() 方法也接受函数以动态计算。可将各种工具作为参数注入这些函数。
若使用 关联分组,可使用 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'));TIP
除静态值外,badgeColor() 与 badgeTooltip() 方法也接受函数以动态计算。可将各种工具作为参数注入这些函数。
延迟加载关联管理器标签页徽章
若 getBadge() 会运行昂贵查询,可将 $isBadgeDeferred 属性设为 true,以延迟徽章,使其在页面渲染后异步加载:
use Illuminate\Database\Eloquent\Model;
protected static bool $isBadgeDeferred = true;
public static function getBadge(Model $ownerRecord, string $pageClass): ?string
{
$count = $ownerRecord->tickets()->count();
return $count > 0 ? (string) $count : null;
}或者,可覆盖 isBadgeDeferred() 方法以定义动态行为:
use Illuminate\Database\Eloquent\Model;
public static function isBadgeDeferred(Model $ownerRecord, string $pageClass): bool
{
return FeatureFlag::active();
}若使用 关联分组,请使用链式 deferBadge() 方法:
use Filament\Resources\RelationManagers\RelationGroup;
RelationGroup::make('Contacts', [
// ...
])
->badge(fn (Model $ownerRecord): string => (string) $ownerRecord->contacts()->count())
->deferBadge();与关联管理器共享资源的表单与表格
你可能希望资源的表单与表格与关联管理器完全相同,从而复用已写的代码。这很简单:从关联管理器调用资源的 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);
}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([
// ...
]);
}DANGER
modifyQueryUsing() 会限定已属于该关联的记录查询——表格列表,以及作用于其行的操作,如 DetachAction、DissociateAction 与批量操作。它不会应用于 AttachAction 或 AssociateAction 可用的记录,因为这些记录按定义在关联之外。
要限制可附加或关联的记录,请在操作上用 recordSelectOptionsQuery() 限定选项。Filament 会按该查询解析提交的记录,因此即使有人篡改提交的模态状态,查询之外的记录也会被拒绝:
use Filament\Actions\AttachAction;
use Illuminate\Database\Eloquent\Builder;
AttachAction::make()
->recordSelectOptionsQuery(fn (Builder $query) => $query->where('is_active', true))自定义关联管理器标题
要设置关联管理器的标题,可在关联管理器类上使用 $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 属性会用于在关联管理器中标识文章。
有时你可能希望拼接多个属性形成标题。可将 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([
// ...
]);
}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'),
];
}WARNING
使用关联页面时,无需用 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',
]),
];
}该属性数组会映射到关联管理器类上的 公开 Livewire 属性:
use Filament\Resources\RelationManagers\RelationManager;
class CommentsRelationManager extends RelationManager
{
public string $status;
// ...
}现在,可在关联管理器类中用 $this->status 访问 status。
禁用懒加载
默认情况下,关联管理器是懒加载的。这意味着它们仅在页面上可见时才会加载。
要禁用此行为,可在关联管理器类上覆盖 $isLazy 属性:
protected static bool $isLazy = false;