Laravel递归验证API请求属性失败的问题及修复
解决动态查询构建器POST请求递归验证失效问题
1. 排查自定义递归规则的核心逻辑
你的问题大概率是自定义RecursiveConditionRule没有正确区分单个条件和条件组的结构,或者递归验证时没有正确传递验证上下文。以Laravel为例,自定义规则的passes方法需要明确判断当前节点类型:
class RecursiveConditionRule implements Rule { private $message; public function passes($attribute, $value) { // 验证单个条件的情况 if (isset($value['type_slug'])) { $validator = Validator::make($value, [ 'type_slug' => 'required|string', 'logical_operator' => 'required|in:eq,neq,gt,lt', 'value' => 'required', // 补充单个条件的其他必填字段规则 ]); if ($validator->fails()) { $this->message = $validator->errors()->first(); return false; } return true; } // 验证条件组的情况 if (isset($value['children'])) { $validator = Validator::make($value, [ 'logical_operator' => 'required|in:and,or', 'children' => 'required|array|min:1', ]); if ($validator->fails()) { $this->message = $validator->errors()->first(); return false; } // 递归验证子条件列表 foreach ($value['children'] as $index => $child) { $childAttr = "{$attribute}.children.{$index}"; if (!$this->passes($childAttr, $child)) { return false; } } return true; } // 不符合任何合法结构的情况 $this->message = "Invalid condition structure at {$attribute}"; return false; } public function message() { return $this->message; } }
2. 修正主验证规则的写法
不要给conditions.*单独加字段级必填规则,而是直接将自定义规则应用到整个conditions数组:
public function rules() { return [ 'conditions' => ['required', 'array', new RecursiveConditionRule], // 其他顶级请求字段的验证规则 ]; }
如果给conditions.*.type_slug这类字段强制加必填规则,会要求所有元素都必须是单个条件,而忽略了条件组的存在,这就是你收到必填错误的核心原因。
3. 对齐请求JSON结构与规则预期
确保你的请求JSON结构和规则判断逻辑一致,比如条件组用children字段嵌套子条件,而非重复使用conditions字段:
{ "conditions": [ { "logical_operator": "and", "children": [ { "type_slug": "user_age", "logical_operator": "gt", "value": 18 }, { "logical_operator": "or", "children": [ { "type_slug": "user_role", "logical_operator": "eq", "value": "admin" } ] } ] } ] }
4. 调试验证过程
在自定义规则的passes方法中添加日志,输出当前验证的$attribute和$value,确认递归时是否正确遍历到所有嵌套节点:
Log::info("Validating node: {$attribute}", $value);
通过日志可以快速定位是某个节点的结构不符合预期,还是递归逻辑没有触发。
内容的提问来源于stack exchange,提问作者Avnee.Angel
相关产品推荐
相关产品推荐

