如何在Laravel中为数组字段组合required_if与required_without验证规则
解决Laravel多站点场景下的联系电话验证问题
业务需求:若站点并非24小时有人值守,则需提供联系电话(固定电话或移动电话均可)。单站点场景下原规则可行,但多站点提交时验证逻辑失效——核心问题是原规则里的通配符*会全局匹配所有站点字段,导致不同站点的验证逻辑相互干扰。
问题分析
原规则中required_if:sites.*.manned_24_hours_a_day,false的写法存在逻辑漏洞:它会检查任意一个站点的manned_24_hours_a_day为false时,就要求当前联系电话字段必填,无法实现“每个站点的联系电话仅关联自身值守状态”的需求。
解决方案
通过循环生成每个站点的独立验证规则,利用Rule::requiredIf回调精准绑定对应站点的值守状态,确保每个站点的验证逻辑完全独立:
use Illuminate\Validation\Rule; public function rules(): array { $rules = [ 'sites.*.manned_24_hours_a_day' => 'required|boolean', ]; $siteCount = count($this->input('sites', [])); for ($i = 0; $i < $siteCount; $i++) { // 处理当前站点下所有联系人的固定电话验证 $rules["sites.{$i}.contacts.*.landline_number"] = [ Rule::requiredIf(function () use ($i) { // 获取当前站点的24小时值守状态 $isManned24 = $this->input("sites.{$i}.manned_24_hours_a_day"); // 获取当前联系人的手机号(若需精准匹配单个联系人,可调整索引) $mobile = $this->input("sites.{$i}.contacts.*.mobile_number"); return !$isManned24 && empty($mobile); }), ]; // 处理当前站点下所有联系人的移动电话验证 $rules["sites.{$i}.contacts.*.mobile_number"] = [ Rule::requiredIf(function () use ($i) { $isManned24 = $this->input("sites.{$i}.manned_24_hours_a_day"); $landline = $this->input("sites.{$i}.contacts.*.landline_number"); return !$isManned24 && empty($landline); }), ]; } return $rules; }
补充说明
- 若每个站点存在多个独立联系人,可嵌套循环处理联系人索引,确保每个联系人的电话验证都严格关联所属站点的值守状态
- 回调中通过
$this->input("sites.{$i}.manned_24_hours_a_day")精准获取对应站点的状态,彻底避免通配符带来的全局匹配问题
内容的提问来源于stack exchange,提问作者John Ascroft
相关产品推荐
相关产品推荐

