如何验证数组中手机号与国家ID的复合唯一性?
解决Laravel数组字段中手机号与国家ID的联合唯一验证问题
当验证数组形式的联系人字段时,原有的单个字段联合唯一规则失效,核心原因是无法正确获取数组中当前项对应的字段值(比如contacts.*.phone和对应的country_id),以下是两种场景的解决方案:
场景1:每个联系人有独立的country_id(请求包含contacts.*.country_id)
使用自定义验证闭包,通过字段属性提取数组索引,获取当前项对应的country_id,再检查联合唯一性:
'contacts.*.phone' => [ 'required', 'string', function ($attribute, $value, $fail) { // 从属性名中拆分出数组索引(如从"contacts.0.phone"得到"0") $index = explode('.', $attribute)[1]; // 获取当前联系人对应的country_id $countryId = $this->input("contacts.$index.country_id"); // 检查users表中是否存在该组合 $exists = \Illuminate\Support\Facades\DB::table('users') ->where('country_id', $countryId) ->where('phone', $value) ->exists(); if ($exists) { $fail("该手机号与国家ID的组合已存在"); } } ],
场景2:country_id为全局字段(整个请求共用同一个country_id)
只需修正规则中获取phone值的方式,使用当前验证项的$value而非根级字段:
'contacts.*.phone' => [ 'required', 'string', function ($attribute, $value, $fail) { $exists = \Illuminate\Support\Facades\DB::table('users') ->where('country_id', $this->country_id) ->where('phone', $value) ->exists(); if ($exists) { $fail("该手机号与国家ID的组合已存在"); } } ],
关键说明
- 原规则失效是因为
$this->phone获取的是请求根级的phone字段,而非数组当前项的phone值;若country_id是数组内字段,$this->country_id也无法定位到当前项的对应值。 - 如果是更新场景,需要排除当前用户记录,可在查询中添加
->whereNot('id', $this->id)(假设请求中包含用户ID)。
内容的提问来源于stack exchange,提问作者meowzart
相关产品推荐
相关产品推荐

