FilamentPHP如何在分类创建表单中实现同模型关联选择
解决方案
1. 先修正分类模型的关联定义
首先确保你的Category模型里正确定义了父子分类的关联关系:
// app/Models/Category.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; class Category extends Model { protected $fillable = ['id', 'slug', 'name', 'parent_id']; // 关联父分类 public function parent(): BelongsTo { return $this->belongsTo(self::class, 'parent_id'); } // 关联子分类(可选,用于展示层级结构) public function children(): HasMany { return $this->hasMany(self::class, 'parent_id'); } }
2. 修正Filament表单代码
你之前的表单代码存在两个核心问题:
- 错误使用
categories作为Select字段名,应该直接绑定parent_id字段 - 关联关系未指向模型里定义的
parent关联
修正后的表单代码如下:
public static function form(Form $form): Form { return $form ->schema([ Forms\Components\TextInput::make('name') ->required() ->maxLength(255), Forms\Components\TextInput::make('slug') ->required() ->maxLength(255) ->unique(ignoreRecord: true), // 可选:确保slug唯一,编辑时忽略当前记录 Forms\Components\Select::make('parent_id') ->label('父分类') ->relationship('parent', 'name') // 关联模型里的parent方法,显示name字段 ->preload() // 预加载所有分类选项 ->searchable() // 支持搜索分类 ->options(function (callable $get) { // 编辑时排除当前分类,避免将自己设为父分类造成循环 $currentCategoryId = $get('id'); return \App\Models\Category::query() ->when($currentCategoryId, fn($query) => $query->where('id', '!=', $currentCategoryId)) ->pluck('name', 'id'); }) ->placeholder('选择父分类(可选)'), ]); }
关键说明
- 移除了原本的
TextInput::make('parent_id'),Select组件会直接处理parent_id的赋值 relationship('parent', 'name')中,第一个参数是模型里定义的关联方法名parent,第二个参数是要显示的字段name- 新增的
options闭包用于在编辑分类时排除自身,防止出现循环引用的层级结构 searchable()和preload()可以提升用户选择分类的操作体验
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

