Laravel关联sync中间表数据时自定义验证规则失效求助
问题原因分析
你的验证规则逻辑错配了——contestants.* 是针对 contestants 数组里的值(也就是每个 {"budget": xxx} 对象)进行验证,而你实际需要验证的是数组的键(也就是选手ID 3、7)是否存在且类型匹配。
Laravel 的数组通配符 * 会遍历数组的每个值,所以你写的 Rule::exists() 是在检查每个预算对象是否是 contestants 表的合法ID,这显然不成立,因此无论数据是否合法都会报错。
解决方法
方法一:通过合并字段验证ID列表
在你的 Form Request 中,先提取 contestants 的键(即选手ID),单独验证这些ID:
- 重写
prepareForValidation方法,把选手ID列表合并到请求中:
protected function prepareForValidation() { $this->merge([ 'contestant_ids' => array_keys($this->input('contestants', [])), ]); }
- 在
rules方法中定义验证规则:
public function rules() { return [ // 验证contestants本身是数组 'contestants' => ['required', 'array'], // 验证每个选手的budget字段 'contestants.*.budget' => ['required', 'numeric', 'min:0'], // 验证选手ID列表是否合法 'contestant_ids' => [ 'required', 'array', Rule::exists('contestants', 'id')->where('contestant_type', $this->game->contestant_type), ], ]; }
方法二:自定义后置验证逻辑
在 withValidator 方法中添加自定义验证逻辑,直接检查 contestants 的键:
public function withValidator($validator) { $validator->after(function ($validator) { $contestants = $this->input('contestants', []); $ids = array_keys($contestants); if (empty($ids)) { return; } // 查询符合条件的合法选手ID $validIds = \App\Models\Contestant::whereIn('id', $ids) ->where('contestant_type', $this->game->contestant_type) ->pluck('id') ->toArray(); // 找出不合法的ID $invalidIds = array_diff($ids, $validIds); if (!empty($invalidIds)) { foreach ($invalidIds as $id) { $validator->errors()->add("contestants.$id", "选手ID {$id} 不存在或与游戏类型不匹配"); } } }); }
这种方法可以直接针对非法ID给出精准的错误提示,不需要额外合并字段。
内容的提问来源于stack exchange,提问作者aznmik
相关产品推荐
相关产品推荐

