Laravel 7数组通配符索引验证消息自定义问询
解决Laravel数组验证自定义消息保留行号的问题
我之前也遇到过类似的困扰,Laravel默认的数组验证消息格式确实不够直观,不过有两种实用的方案可以满足你的需求——既保留行号,又不用全局覆盖所有规则的消息:
方案一:针对特定字段/规则用闭包自定义消息
这种方法适合你只需要在某一处验证中修改消息格式的场景,直接在验证器实例中通过闭包动态生成消息,完美保留行号:
$validator = Validator::make($array, [ '*.client_name' => 'required', '*.client_phone' => ['required', 'regex:/^(0)(5|6|7)[0-9]{8}/'], ], [ // 针对client_name的required规则自定义消息 '*.client_name.required' => function ($attribute, $parameters, $validator) { // 拆分属性名,比如把"1.client_name"拆成行号和字段名 [$row, $field] = explode('.', $attribute); return "Row {$row} : The field {$field} is required"; }, // 针对client_phone的required规则 '*.client_phone.required' => function ($attribute, $parameters, $validator) { [$row, $field] = explode('.', $attribute); return "Row {$row} : The field {$field} is required"; }, // 针对client_phone的regex规则 '*.client_phone.regex' => function ($attribute, $parameters, $validator) { [$row, $field] = explode('.', $attribute); return "Row {$row} : The field {$field} must match the correct phone number format"; }, ]); $validator->validate();
闭包会接收当前的属性名(已经替换了*为实际行号,比如1.client_name),我们只需要拆分出数字和字段名,再拼接成想要的格式即可。
方案二:全局注册验证消息替换器
如果你的项目中有多处数组验证需要统一这种消息格式,推荐在AppServiceProvider中注册全局替换器,一劳永逸:
// app/Providers/AppServiceProvider.php use Illuminate\Support\Facades\Validator; public function boot() { // 给required规则注册替换逻辑 Validator::replacer('required', function ($message, $attribute, $rule, $parameters) { // 判断是否是数组字段(包含小数点) if (str_contains($attribute, '.')) { // 拆分行号和字段名,第二个参数2确保只拆一次(防止字段名含小数点) [$row, $field] = explode('.', $attribute, 2); // 替换原消息中的:attribute占位符 return str_replace(':attribute', "Row {$row} : The field {$field}", $message); } // 非数组字段保持原有消息格式 return $message; }); // 同样给regex规则注册替换逻辑 Validator::replacer('regex', function ($message, $attribute, $rule, $parameters) { if (str_contains($attribute, '.')) { [$row, $field] = explode('.', $attribute, 2); return str_replace(':attribute', "Row {$row} : The field {$field}", $message); } return $message; }); }
这样所有数组字段的required和regex规则都会自动生成你想要的消息格式,而且完全不影响非数组字段的验证消息。
为什么setAttributeNames不行?
你提到用setAttributeNames时丢失行号,是因为Laravel在验证数组时,会把*.client_name中的*替换成实际的索引(比如1),变成1.client_name,而setAttributeNames里的*.client_name无法匹配到这个动态生成的属性名,所以没办法正确替换,自然就丢失了行号信息。
内容的提问来源于stack exchange,提问作者Wildfire
相关产品推荐
相关产品推荐

