如何根据关联模型数据动态设置字段为必填项?
根据所选Specialty动态设置字段必填性(Filament PHP v3)
包版本
- PHP 8.2.12
- Laravel 10.28.0
- Filamentphp v3
需求说明
现有两个模型:
Candidat(id, name, specialty_id):关联Specialty模型Specialty(id, name, is_required):is_required为布尔类型字段
需要实现:根据用户选择的specialty,动态设置copie_permis文件上传字段是否为必填项——当所选Specialty的is_required为true时,该字段必填;反之则非必填。
当前代码
Forms\Components\Select::make('specialty_id') ->required() ->live() ->searchable()->preload() ->relationship('specialty','name'), Forms\Components\FileUpload::make('copie_permis') ->directory('permis_files') ->openable() ->downloadable() ->image() ->imageEditor() ->required(fn (Get $get): bool => ($get('specialty_id.is_required') == true)),
问题分析
当前代码中$get('specialty_id.is_required')无法正确获取值,因为specialty_id存储的是关联模型的ID,而非模型对象本身,无法直接通过这种方式访问关联属性。
修复方案
方案一:直接查询数据库获取属性值
通过选中的specialty_id查询对应Specialty模型的is_required字段:
Forms\Components\Select::make('specialty_id') ->required() ->live() ->searchable() ->preload() ->relationship('specialty', 'name'), Forms\Components\FileUpload::make('copie_permis') ->directory('permis_files') ->openable() ->downloadable() ->image() ->imageEditor() ->required(function (Get $get) { $specialtyId = $get('specialty_id'); // 未选择专业时,默认非必填 if (!$specialtyId) return false; // 查询对应专业的is_required值 return \App\Models\Specialty::find($specialtyId)->is_required; }),
方案二:预加载选项时携带属性(更高效)
在Select组件加载选项时,将is_required信息一并返回,避免每次切换都查询数据库:
Forms\Components\Select::make('specialty_id') ->required() ->live() ->searchable() ->preload() // 自定义选项,包含name和is_required ->options(function () { return \App\Models\Specialty::all()->mapWithKeys(function ($specialty) { return [ $specialty->id => [ 'name' => $specialty->name, 'is_required' => $specialty->is_required ] ]; }); }) // 设置选项显示的标签为name ->getOptionLabelUsing(fn ($value) => $value['name']), Forms\Components\FileUpload::make('copie_permis') ->directory('permis_files') ->openable() ->downloadable() ->image() ->imageEditor() ->required(function (Get $get) { $selectedSpecialty = $get('specialty_id'); return $selectedSpecialty ? $selectedSpecialty['is_required'] : false; }),
注意事项
- 方案一适合数据量较小的场景,每次切换专业会触发一次数据库查询;
- 方案二一次性加载所有专业数据,避免重复查询,性能更优;
- 请根据自己项目的模型命名空间调整
\App\Models\Specialty路径。
内容的提问来源于stack exchange,提问作者MENKOUSS Med Abdellahi
相关产品推荐
相关产品推荐

