Laravel验证:如何确保mapping_list数组至少一个text字段非空
问题描述
请求数据示例:
[2022-12-07 11:56:19] local.INFO: array ( 'name' => NULL, 'import_period' => NULL, 'google_ads_account' => NULL, 'period' => NULL, 'period_date_from' => NULL, 'period_date_to' => NULL, 'id_campaigns' => array ( 0 => array ( 'id_campaign' => NULL, ), ), 'id_adgroups' => array ( 0 => array ( 'id_adgroup' => NULL, ), ), 'campaign_name_contains' => NULL, 'adgroup_name_contains' => NULL, 'click' => 'less_than', 'click_value' => NULL, 'click_from' => NULL, 'click_to' => NULL, 'impressions' => 'less_than', 'impressions_value' => NULL, 'impressions_from' => NULL, 'impressions_to' => NULL, 'cost' => 'less_than', 'cost_value' => NULL, 'cost_from' => NULL, 'cost_to' => NULL, 'conversions' => 'less_than', 'conversions_value' => NULL, 'conversions_from' => NULL, 'conversions_to' => NULL, 'mapping_list' => array ( 0 => array ( 'value' => 'conversions', 'text' => NULL, ), 1 => array ( 'value' => 'roas', 'text' => NULL, ), 2 => array ( 'value' => 'all_conversions', 'text' => NULL, ), 3 => array ( 'value' => 'all_conversions_from_interactions_rate', 'text' => NULL, ), 4 => array ( 'value' => 'ctr', 'text' => NULL, ), 5 => array ( 'value' => 'average_cpc', 'text' => NULL, ), 6 => array ( 'value' => 'clicks', 'text' => NULL, ), 7 => array ( 'value' => 'impressions', 'text' => NULL, ), 8 => array ( 'value' => 'cost', 'text' => NULL, ), 9 => array ( 'value' => 'conversions_value', 'text' => NULL, ), 10 => array ( 'value' => 'conversions_from_interactions_rate', 'text' => NULL, ), 11 => array ( 'value' => 'cost_per_conversion', 'text' => NULL, ), 12 => array ( 'value' => 'search_click_share', 'text' => NULL, ), 13 => array ( 'value' => 'search_impression_share', 'text' => NULL, ), 14 => array ( 'value' => 'value_per_all_conversions', 'text' => NULL, ), 15 => array ( 'value' => 'value_per_conversion', 'text' => NULL, ), ), )
使用的Laravel验证规则:
$validator = Validator::make($request->all(), [ 'name' => 'required', 'import_period' => 'required', 'google_ads_account' => 'required', 'period' => 'required', 'period_date_from' => 'required_if:period,custom', 'period_date_to' => 'required_if:period,custom', 'id_campaigns.*.id_campaign'=> 'required', 'id_adgroups.*.id_adgroup' => 'required', 'campaign_name_contains' => 'required', 'adgroup_name_contains' => 'required', 'mapping_list.*.text' => 'required|min:1', 'click' => 'required', 'click_value' => 'required_if:click,greater_than,less_than', 'click_from' => 'required_if:click,between', 'click_to' => 'required_if:click,between', 'cost' => 'required', 'cost_value' => 'required_if:cost,greater_than,less_than', 'cost_from' => 'required_if:cost,between', 'cost_to' => 'required_if:cost,between', 'impressions' => 'required', 'impressions_value' => 'required_if:impressions,greater_than,less_than', 'impressions_from' => 'required_if:impressions,between', 'impressions_to' => 'required_if:impressions,between', 'conversions' => 'required', 'conversions_value' => 'required_if:conversions,greater_than,less_than', 'conversions_from' => 'required_if:conversions,between', 'conversions_to' => 'required_if:conversions,between', ]);
原本期望mapping_list数组中至少一个text字段被填写,但当前规则要求必须填写所有元素的text字段,请问哪里操作有误?
问题原因
你使用的mapping_list.*.text规则中,*是Laravel的数组通配符,作用是遍历mapping_list数组中的每一个元素,对每个元素的text字段单独应用required|min:1校验,这就会强制要求所有元素的text都必须填写,和你“至少一个填写”的需求不符。
解决方案
移除原来的'mapping_list.*.text' => 'required|min:1'规则,改为对整个mapping_list数组添加自定义校验逻辑,检查数组中是否存在至少一个text不为空的元素:
$validator = Validator::make($request->all(), [ // 保留原有其他所有规则 'mapping_list' => [ 'required', function ($attribute, $value, $fail) { // 用collect包装数组,检查是否有至少一个元素的text不为空(含去空格校验) $hasFilledText = collect($value)->some(function ($item) { return !empty(trim($item['text'])); }); if (!$hasFilledText) { $fail('至少需要填写一个映射项的文本内容。'); } }, ], ]);
补充说明
- 自定义闭包里的
trim是可选的,用来排除仅填写空格的无效内容,可根据实际需求调整; - 若需要复用该校验逻辑,可以把它封装成自定义验证规则类,方便在多个地方调用。
内容的提问来源于stack exchange,提问作者Shibbir
相关产品推荐
相关产品推荐

