You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel FormRequest验证GET请求JSON查询参数失效排查

问题分析与解决方案

核心问题在于你用json_decode()解码JSON字符串时返回的是PHP stdClass对象,而Laravel的嵌套数组验证规则(如*.name)仅对关联数组生效。当验证器遇到对象时,无法解析嵌套属性的验证规则,只会执行顶层的required和array检查,嵌套规则直接跳过,同时会将无法验证的对象属性置空,但不会触发422验证失败响应。

修复步骤

1. 将JSON解码为关联数组

修改prepareForValidation()中的json_decode调用,添加第二个参数true,强制返回关联数组:

protected function prepareForValidation(): void
{
    try {
        $sorters = null;
        if ($this->query->has('sorters')) {
            // 解码为关联数组
            $sorters = json_decode($this->query->get('sorters'), true);
            $this->merge([
                'sorters_decoded' => $sorters,
            ]);
        }

        $filters = null;
        if ($this->query->has('filters')) {
            // 解码为关联数组
            $filters = json_decode($this->query->get('filters'), true);
            $this->merge([
                'filters_decoded' => $filters,
            ]);
        }

        $this->merge([
            'language' => $this->headers->get('language'),
        ]);
    } catch(\Throwable $e) {
        // 可在此处记录日志,无需静默忽略
        // Log::error('JSON解码失败: ' . $e->getMessage());
    }
}

2. 调整可选参数的验证规则(可选)

如果sorters和filters是可选查询参数,需要将对应的_decoded字段规则从required改为nullable,同时给嵌套规则添加required_with约束,避免用户未传参数时触发不必要的验证失败:

public function rules(): array
{
    return [
        'sorters' => ['nullable', 'json'],
        'sorters_decoded' => ['nullable', 'array'],
        'sorters_decoded.*.name' => ['required_with:sorters_decoded', 'string', Rule::in(['likes', 'ratings', 'calories', 'carbs', 'protein', 'fat', 'created'])],
        'sorters_decoded.*.direction' => ['required_with:sorters_decoded', 'string', Rule::in(['asc', 'desc'])],
        'sorters_decoded.*.order' => ['required_with:sorters_decoded', 'integer'],
        'filters' => ['nullable', 'json'],
        'filters_decoded' => ['nullable', 'array'],
        'filters_decoded.duration_high' => ['required_with:filters_decoded', 'integer', 'min:0'],
        'filters_decoded.duration_low' => ['required_with:filters_decoded', 'integer', 'min:0'],
        'filters_decoded.title' => ['required_with:filters_decoded', 'string'],
        'filters_decoded.difficulty' => ['required_with:filters_decoded', 'array'],
        'filters_decoded.difficulty.*' => ['string', 'exists:difficulties,id'],
        'filters_decoded.ingredients' => ['required_with:filters_decoded', 'array'],
        'filters_decoded.ingredients.*.id' => ['string', 'exists:ingredients,id'],
        'filters_decoded.ingredients.*.relation' => ['string', Rule::in(['include', 'exclude'])],
        'filters_decoded.liked_by_me' => ['required_with:filters_decoded', 'boolean'],
        'filters_decoded.cookbooks' => ['required_with:filters_decoded', 'array'],
        'filters_decoded.cookbooks.*' => ['string', 'exists:cookbooks,id'],
        'filters_decoded.nutritions' => ['required_with:filters_decoded', 'array'],
        'filters_decoded.nutritions.*.category_id' => ['string', 'exists:nutrition_categories,id'],
        'filters_decoded.nutritions.*.nutrition_high' => ['numeric', 'min:0'],
        'filters_decoded.nutritions.*.nutrition_low' => ['numeric', 'min:0'],
        'language' => ['string', 'size:2', 'exists:i18n_languages,short'],
        'page' => ['integer', 'min:1'],
        'per_page' => ['integer', 'min:1'],
    ];
}

3. 强化JSON解码失败处理(可选)

虽然sorters和filters已添加json规则,Laravel会自动验证格式,但如果需要更明确的错误提示,可以在解码后主动检查结果:

if ($this->query->has('sorters')) {
    $sorters = json_decode($this->query->get('sorters'), true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        // 手动触发JSON格式验证失败
        $this->merge(['sorters' => 'invalid_json']);
    }
    $this->merge(['sorters_decoded' => $sorters]);
}

验证逻辑说明

当JSON被解码为关联数组后,Laravel的验证器可以正确识别嵌套结构,执行元素级规则校验。一旦数据不符合规则,会立即返回422响应并携带具体错误信息,而非仅置空非法数据。

内容的提问来源于stack exchange,提问作者MikkeyDevelop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:02:14