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

Laravel验证中如何访问当前迭代的嵌套值?

Laravel嵌套数组验证:动态忽略当前tagId对应的唯一名称

问题需求

在Laravel中验证嵌套数组tagDetails时,需满足以下规则:

  • tagId字段在数组内唯一
  • name字段在数组内唯一,且无tagId时必填
  • 验证name在tag_masters表的唯一性时,需忽略当前迭代项中tagId对应的数据库记录,但无法直接获取当前迭代的tagId值

现有验证代码

Validator::make([
    'tagDetails' => ['required', 'array'],
    'tagDetails.*.tagId' => ['distinct'],
    'tagDetails.*.name' => [
        'distinct',
        'required_without:tagDetails.*.tagId',
        Rule::unique('tag_masters', 'name')
        ->ignore(
           ( !empty( //want to access current iteration tagId Value ))
        ),
    ]
])

请求示例

{
    "name": "test",
    "tagDetails": [
        {
            "tagId": "123",
            "name" : "Tag1",
            "hexColorCode" : "#FF1931"
        },
        {
            "tagId": "4556",
            "name" : "Tag2",
            "hexColorCode" : "#FF1931"
        }
    ]
}

尝试的无效代码

Validator::make([
    'tagDetails' => ['required', 'array'],
    'tagDetails.*.tagId' => ['distinct'],
    'tagDetails.*.name' => [
        'distinct',
        'required_without: tagDetails.*.tagId',
        Rule::unique('tag_masters', 'name')
            ->ignore(
               (!empty($this->tagDetails.*.tagId))
            ),
    ]
])

解决方案

无法直接通过通配符在Rule::unique的ignore方法中获取当前迭代的tagId,需通过自定义闭包验证实现动态逻辑:

use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;

$validator = Validator::make($request->all(), [
    'tagDetails' => ['required', 'array'],
    'tagDetails.*.tagId' => ['distinct'],
    'tagDetails.*.name' => [
        'distinct',
        'required_without:tagDetails.*.tagId',
        function ($attribute, $value, $fail) use ($request) {
            // 从字段名提取当前迭代索引(如从"tagDetails.0.name"得到索引0)
            $parts = explode('.', $attribute);
            $index = $parts[1];
            
            // 获取当前项的tagId
            $currentTagId = $request->input("tagDetails.$index.tagId");
            
            // 检查name是否重复,存在tagId则排除对应记录
            $isDuplicate = DB::table('tag_masters')
                ->where('name', $value)
                ->when($currentTagId, function ($query) use ($currentTagId) {
                    $query->where('id', '!=', $currentTagId);
                })
                ->exists();
                
            if ($isDuplicate) {
                $fail('该标签名称已存在');
            }
        },
    ],
]);

// 执行验证逻辑
if ($validator->fails()) {
    // 处理验证错误
}

关键说明

  1. 索引提取:通过拆分验证字段名的方式,定位到当前迭代项的位置,从而获取对应的tagId。
  2. 动态查询:使用when方法实现条件查询,当存在tagId时排除该记录,否则直接检查名称唯一性。
  3. 双重唯一性:distinct规则保证数组内字段唯一,自定义闭包保证数据库层面的唯一验证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 01:45:16