Filament非模型关联Select表单批量赋值报错解决方案咨询
解决Filament中非模型字段的批量赋值错误问题
在Filament中处理表单里的非模型字段时,不需要修改模型的$fillable(这确实是不良实践),用以下两种原生方案即可解决:
方案1:保存前过滤非模型字段
利用Resource的mutateFormDataBeforeSave钩子,在表单数据写入模型前移除不属于模型的字段,从根源避免批量赋值报错。
use Filament\Resources\Resource; use Filament\Forms\Form; class CargoCustomLogicResource extends Resource { // 其他Resource配置(模型、路由等) public static function form(Form $form): Form { return $form ->schema([ // 模型原有字段示例 TextInput::make('title')->required(), // 非模型字段 Select::make('load_points_city') ->options(['bj' => '北京', 'sh' => '上海']), Select::make('cargo_type_id') ->options(\App\Models\CargoType::pluck('name', 'id')), ]); } protected function mutateFormDataBeforeSave(array $data): array { // 移除所有非模型字段,只保留模型可填充的字段 unset($data['load_points_city'], $data['cargo_type_id']); // 如果需要用这些字段执行额外逻辑,在这里处理 // 示例:$this->syncCargoType($data['cargo_type_id'], $this->record); return $data; } }
方案2:结合afterSave处理非模型字段逻辑
如果非模型字段需要用来触发后续业务逻辑(比如创建关联、调用接口),可以先保留字段值,在afterSave钩子中处理,同时依然要过滤字段避免批量赋值错误。
public static function form(Form $form): Form { return $form ->schema([ // 模型字段... // 非模型字段正常渲染,不需要隐藏 Select::make('load_points_city') ->options(['bj' => '北京', 'sh' => '上海']), Select::make('cargo_type_id') ->options(\App\Models\CargoType::pluck('name', 'id')), ]); } protected function afterSave(\App\Models\CargoCustomLogic $record, array $data): void { // 在这里使用非模型字段的值处理业务 if (isset($data['cargo_type_id'])) { $record->cargoTypes()->attach($data['cargo_type_id']); } } // 必须过滤非模型字段,防止批量赋值报错 protected function mutateFormDataBeforeSave(array $data): array { unset($data['load_points_city'], $data['cargo_type_id']); return $data; }
额外提示
如果非模型字段仅用于前端交互(比如动态联动其他表单字段),可以给字段加上live()方法,不需要提交到后端,自然不会触发批量赋值问题:
Select::make('load_points_city') ->options(['bj' => '北京', 'sh' => '上海']) ->live() ->afterStateUpdated(function (callable $set, $state) { // 联动其他字段,比如根据城市设置默认仓库 $set('warehouse_id', $this->getDefaultWarehouseByCity($state)); });
内容的提问来源于stack exchange,提问作者Vitaly Vesyolko
相关产品推荐
相关产品推荐

