Filament PHP中如何用MorphToSelect实现关联下拉选择?
问题
我需要创建一个关联下拉选择组件,让第二个下拉框的选项基于MorphToSelect组件的选中值(模型类型与ID)。但遇到两个问题:
reactive()方法在MorphToSelect组件上似乎无效- 无法正确获取该组件的选中值
我尝试给MorphToSelect添加reactive()和afterStateUpdated闭包,同时在关联下拉框中用$get获取值,但都没生效,相关代码如下:
return $form ->schema([ MorphToSelect::make('payable') ->label('Availment Classification') ->types([ MorphToSelect\Type::make(Customer::class)->titleColumnName('name'), MorphToSelect\Type::make(User::class)->titleColumnName('name') ->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereDoesntHave('customer') ->whereDoesntHave('roles.permissions', function ($query) { $query->where('id',36); }) ), ]) ->required() ->preload() ->searchable() ->reactive() ->afterStateUpdated(fn(callable $set) => $set('payment_model_handle',null)) ->columnSpanFull(), Fieldset::make('Payment Model') ->schema([ Select::make('payment_model_handle') ->searchable() ->columnSpanFull() ->label('Payment Model') ->relationship('AvailedPaymentModels','handle') ->preload() ->required() ->options(function(callable $get, Closure $set){ $payable = $get('payable'); $id = $payable['id'] ?? null; $type = $payable['type'] ?? null; $options = PaymentModel::whereDoesntHave('availedPaymentModels', function ($query) use($id,$type) { $query->where('payable_id', $id) ->where('payable_type', $type); })->pluck('handle', 'id'); return $options; }) ]) ]);
解决方案
核心修正点
- 依赖关联触发:给关联的
Select组件添加dependsOn('payable'),明确它依赖payable字段的状态变化,确保payable变更时重新计算选项 - 空值安全处理:在
options闭包中增加空值判断,避免$id或$type为空时触发无效数据库查询 - 状态同步保障:确认
MorphToSelect的reactive()调用生效,配合afterStateUpdated清空关联字段的逻辑
修正后的完整代码
return $form ->schema([ MorphToSelect::make('payable') ->label('Availment Classification') ->types([ MorphToSelect\Type::make(Customer::class)->titleColumnName('name'), MorphToSelect\Type::make(User::class)->titleColumnName('name') ->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereDoesntHave('customer') ->whereDoesntHave('roles.permissions', function ($query) { $query->where('id', 36); }) ), ]) ->required() ->preload() ->searchable() ->reactive() ->afterStateUpdated(fn(callable $set) => $set('payment_model_handle', null)) ->columnSpanFull(), Fieldset::make('Payment Model') ->schema([ Select::make('payment_model_handle') ->searchable() ->columnSpanFull() ->label('Payment Model') ->relationship('AvailedPaymentModels', 'handle') ->preload() ->required() // 绑定依赖字段,实时响应payable的变更 ->dependsOn('payable', function (Select $component) { $component->refresh(); }) ->options(function(callable $get){ $payable = $get('payable'); $id = $payable['id'] ?? null; $type = $payable['type'] ?? null; // 空值时返回空集合,避免无效查询 if (empty($id) || empty($type)) { return collect(); } $options = PaymentModel::whereDoesntHave('availedPaymentModels', function ($query) use($id,$type) { $query->where('payable_id', $id) ->where('payable_type', $type); })->pluck('handle', 'id'); return $options; }) ]) ]);
关键说明
dependsOn('payable')是让Select组件监听payable的状态变化,一旦payable选中值变更,就会重新执行options闭包生成新的选项列表- 通过
$get('payable')获取的是包含type和id的数组,提取这两个值的逻辑是正确的,只需确保状态能实时同步 afterStateUpdated中清空payment_model_handle的逻辑保留,确保切换分类后关联选项被重置
内容的提问来源于stack exchange,提问作者Aries DevSec
相关产品推荐
相关产品推荐

