Laravel中hasMany关联子项更新时的唯一性验证问题
Laravel更新父模型时验证子项Code唯一性(忽略自身ID)
方案一:自定义闭包验证
直接通过闭包解析当前子项ID,排除自身后检查Code唯一性:
$parent = Parent::find($id); $rules = [ 'code' => ['required', Rule::unique('parents', 'code')->ignore($parent->id)], 'childrens.*.code' => [ 'required', function ($attribute, $value, $fail) use ($parent) { // 拆分属性名获取子项索引,比如 "childrens.2.code" 拆出索引2 $index = explode('.', $attribute)[1]; // 获取当前子项的ID(新增子项时该值为null) $childId = request()->input("childrens.$index.id"); // 构建查询:检查code是否存在,排除自身ID $query = \App\Models\Children::where('code', $value); if ($childId) { $query->where('id', '!=', $childId); } // 若业务要求子项Code仅在所属父模型下唯一,取消下面注释 // $query->where('parent_id', $parent->id); if ($query->exists()) { $fail('该子项编码已存在'); } } ], ];
方案二:动态使用Rule::unique的ignore方法
利用Laravel内置规则,通过闭包动态获取当前子项ID并忽略:
use Illuminate\Validation\Rule; $parent = Parent::find($id); $rules = [ 'code' => ['required', Rule::unique('parents', 'code')->ignore($parent->id)], 'childrens.*.code' => [ 'required', Rule::unique('childrens', 'code') ->ignore(function ($value, $attribute) { $index = explode('.', $attribute)[1]; // 新增子项时无ID,ignore(0)不影响(数据库ID通常从1开始) return request()->input("childrens.$index.id") ?? 0; }) // 若需父模型内唯一,添加下面的where条件 // ->where('parent_id', $parent->id) ], ];
注意事项
- 更新子项时,请求的
childrens数组必须包含已有子项的id字段,新增子项可省略id。 - 如果业务规则是子项Code仅在所属父模型下唯一,务必添加
where('parent_id', $parent->id)条件,避免跨父模型的Code冲突。
内容的提问来源于stack exchange,提问作者GAOUL
相关产品推荐
相关产品推荐

