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()) { // 处理验证错误 }
关键说明
- 索引提取:通过拆分验证字段名的方式,定位到当前迭代项的位置,从而获取对应的
tagId。 - 动态查询:使用
when方法实现条件查询,当存在tagId时排除该记录,否则直接检查名称唯一性。 - 双重唯一性:
distinct规则保证数组内字段唯一,自定义闭包保证数据库层面的唯一验证。
内容的提问来源于stack exchange,提问作者Archit Gupta
相关产品推荐
相关产品推荐

