Filament Form Builder:多对多关联中如何填充Pivot表属性?
解决Filament Form Builder多对多关联Pivot字段填充问题
1. 模型层配置
先确保主模型与关联模型的多对多关系中,声明需要维护的pivot字段:
// Famille.php public function personnes() { return $this->belongsToMany(Personne::class) ->withPivot('categorie_id') // 明确指定要处理的pivot字段 ->withTimestamps(); // 若pivot表包含时间戳字段需添加 }
// Personne.php public function familles() { return $this->belongsToMany(Famille::class) ->withPivot('categorie_id') ->withTimestamps(); }
2. 确认数据库表结构
检查pivot表(例如famille_personne)的迁移文件,确保包含categorie_id字段:
// 迁移文件示例 public function up() { Schema::create('famille_personne', function (Blueprint $table) { $table->foreignId('famille_id')->constrained()->onDelete('cascade'); $table->foreignId('personne_id')->constrained()->onDelete('cascade'); $table->foreignId('categorie_id')->constrained()->onDelete('cascade'); $table->timestamps(); $table->primary(['famille_id', 'personne_id']); }); }
3. 表单层自定义关联保存逻辑
根据业务场景选择对应实现方式:
场景1:所有关联Personne共用同一个Categorie
如果categorie_id是表单统一选择的值,在MultiSelect关联字段中通过saveUsing()自定义保存逻辑:
use Filament\Forms\Components\MultiSelect; use Filament\Forms\Components\Select; use Filament\Forms\Form; public function form(Form $form): Form { return $form ->schema([ // 其他Famille字段... Select::make('categorie_id') ->relationship('categories', 'name') ->required() ->label('关联分类'), MultiSelect::make('personnes') ->relationship('personnes', 'name') ->required() ->label('关联人员') ->saveUsing(function ($record, $state) { // 清空已有关联 $record->personnes()->detach(); // 遍历选中的Personne ID,附加关联并设置pivot字段 $categorieId = $this->form->getState()['categorie_id']; foreach ($state as $personneId) { $record->personnes()->attach($personneId, [ 'categorie_id' => $categorieId, ]); } }), ]); }
场景2:每个关联Personne单独选择对应的Categorie
需要为每个选中的Personne单独指定Categorie时,用Repeater组件实现多组选择再批量保存:
use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Select; use Filament\Forms\Form; public function form(Form $form): Form { return $form ->schema([ // 其他Famille字段... Repeater::make('personne_categorie') ->schema([ Select::make('personne_id') ->relationship('personnes', 'name') ->required() ->label('选择人员'), Select::make('categorie_id') ->relationship('categories', 'name') ->required() ->label('选择分类'), ]) ->minItems(1) ->label('人员-分类关联') ->saveUsing(function ($record, $state) { $record->personnes()->detach(); foreach ($state as $item) { $record->personnes()->attach($item['personne_id'], [ 'categorie_id' => $item['categorie_id'], ]); } }), ]); }
场景3:自动从Personne模型获取Categorie ID
如果categorie_id是Personne模型的固有属性,无需用户选择,直接在保存时读取:
MultiSelect::make('personnes') ->relationship('personnes', 'name') ->required() ->saveUsing(function ($record, $state) { $record->personnes()->detach(); foreach ($state as $personneId) { $personne = Personne::findOrFail($personneId); $record->personnes()->attach($personneId, [ 'categorie_id' => $personne->categorie_id, ]); } }),
内容的提问来源于stack exchange,提问作者Benzaza Laid
相关产品推荐
相关产品推荐

