
本教程详细讲解如何在laravel应用中实现多语言验证错误消息的并行展示。通过重写formrequest的`messages`方法,为每个验证规则和字段定制多语言错误信息,并结合`failedvalidation`方法进行响应格式化,从而在单个api响应中同时返回不同语言的验证结果,满足复杂的国际化需求。
Laravel多语言验证错误消息的并行展示
在构建国际化(i18n)API时,一个常见的需求是能够在单个API响应中,为同一个字段的验证错误同时提供多种语言的提示。Laravel的FormRequest默认行为是根据当前的应用程序语言环境(Locale)返回验证错误信息。然而,当我们需要一个统一的响应结构,例如,某个字段的错误信息同时包含英文和法文版本时,默认机制就显得不足了。
核心挑战与目标响应结构
传统的Laravel验证流程中,当验证失败时,FormRequest会调用failedValidation方法,并传入一个已经根据当前Locale生成好消息的MessageBag实例。这意味着在failedValidation阶段,我们已经无法轻易地为同一个错误动态地生成其他语言的消息。
我们的目标是实现以下类似的多语言错误响应结构:
{ "detail": { "email": { "en-CA" : [ "The email has already been taken." ], "fr-CA" : [ "The french text." ] }, "first_name": { "en-CA" : [ "The first name must be at least 5.", "The first name must be an integer." ], "fr-CA" : [ "The french text", "The french text." ] } }}
要实现这种结构,我们需要在验证器生成错误消息的阶段就介入,而不是在消息生成完毕后尝试转换。
解决方案:重写FormRequest的messages()方法
Laravel的FormRequest提供了一个messages()方法,允许开发者为每个验证规则和字段定制错误消息。这是在验证器生成MessageBag之前介入的关键点。通过在此方法中明确指定每种语言的错误消息,我们可以确保MessageBag在构建时就包含了所有必要的多语言信息。
1. 定义验证规则
首先,像往常一样在FormRequest中定义你的验证规则。例如:
// app/Http/Requests/SysUserStoreRequest.phpnamespace AppHttpRequests;use IlluminateFoundationHttpFormRequest;class SysUserStoreRequest extends ApiRequest // 假设ApiRequest是你的基类FormRequest{ public function rules() { return [ 'email' => 'required|email|unique:users,email,' . $this->id, 'first_name' => 'required|string|min:5', // ... 其他字段规则 ]; } // ... 其他方法}
2. 实现多语言消息生成
在SysUserStoreRequest中重写messages()方法,为每个字段和规则定义多语言错误信息。
// app/Http/Requests/SysUserStoreRequest.phpnamespace AppHttpRequests;use IlluminateFoundationHttpFormRequest;use IlluminateContractsValidationValidator;use IlluminateHttpExceptionsHttpResponseException;class SysUserStoreRequest extends ApiRequest{ public function rules() { return [ 'email' => 'required|email|unique:users,email,' . ($this->id ?? 'NULL'), // 确保unique规则在更新时能排除自身 'first_name' => 'required|string|min:5', // ... ]; } public function messages() { return [ 'email.required' => [ 'en-CA' => __('validation.required', ['attribute' => __('portal.email', [], 'en-CA')], 'en-CA'), 'fr-CA' => __('validation.required', ['attribute' => __('portal.email', [], 'fr-CA')], 'fr-CA'), ], 'email.email' => [ 'en-CA' => __('validation.email', ['attribute' => __('portal.email', [], 'en-CA')], 'en-CA'), 'fr-CA' => __('validation.email', ['attribute' => __('portal.email', [], 'fr-CA')], 'fr-CA'), ], 'email.unique' => [ 'en-CA' => __('validation.unique', ['attribute' => __('portal.email', [], 'en-CA')], 'en-CA'), 'fr-CA' => __('validation.unique', ['attribute' => __('portal.email', [], 'fr-CA')], 'fr-CA'), ], 'first_name.required' => [ 'en-CA' => __('validation.required', ['attribute' => __('portal.first_name', [], 'en-CA')], 'en-CA'), 'fr-CA' => __('validation.required', ['attribute' => __('portal.first_name', [], 'fr-CA')], 'fr-CA'), ], 'first_name.min' => [ 'en-CA' => __('validation.min.string', ['attribute' => __('portal.first_name', [], 'en-CA'), 'min' => 5], 'en-CA'), 'fr-CA' => __('validation.min.string', ['attribute' => __('portal.first_name', [], 'fr-CA'), 'min' => 5], 'fr-CA'), ], // ... 为其他字段和规则添加类似的多语言消息 ]; }}
代码解释:
’email.required’:这是消息键,由字段名和验证规则名组成。[ ‘en-CA’ => …, ‘fr-CA’ => … ]:值是一个关联数组,键是目标语言环境代码(例如en-CA, fr-CA),值是该语言环境下的具体错误消息。__(‘validation.required’, [‘attribute’ => __(‘portal.email’, [], ‘en-CA’)], ‘en-CA’):__(‘validation.required’, …, ‘en-CA’):这是Laravel的翻译辅助函数,用于从lang/en-CA/validation.php文件中获取required规则的原始消息。第三个参数’en-CA’明确指定了要使用的语言文件。[‘attribute’ => __(‘portal.email’, [], ‘en-CA’)]:这是用于替换验证消息中占位符(如:attribute)的参数。这里我们再次使用__函数来翻译字段名本身(例如,从lang/en-CA/portal.php获取email的翻译),确保整个错误消息是完全本地化的。对于带有min、max等参数的规则,需要传递相应的参数,例如’min’ => 5。
通过这种方式,当验证失败时,Validator的MessageBag中,每个错误消息项将不再是简单的字符串,而是一个包含所有指定语言消息的数组。例如,$validator->getMessageBag()->toArray()可能会返回类似:[’email’ => [[‘en-CA’ => ‘…’, ‘fr-CA’ => ‘…’]]]
格式化最终API响应:重写failedValidation()
尽管messages()方法帮助我们生成了多语言数据,但MessageBag的默认结构可能不完全符合我们期望的最终JSON格式。我们需要在ApiRequest(或你的基础FormRequest类)中重写failedValidation方法,将MessageBag的内容转换为目标结构。
// app/Http/Requests/ApiRequest.phpnamespace AppHttpRequests;use IlluminateFoundationHttpFormRequest;use IlluminateContractsValidationValidator;use IlluminateHttpExceptionsHttpResponseException;abstract class ApiRequest extends FormRequest{ /** * Handle a failed validation attempt. * * @param IlluminateContractsValidationValidator $validator * @return void * * @throws IlluminateHttpExceptionsHttpResponseException */ protected function failedValidation(Validator $validator) { $errors = $validator->getMessageBag()->toArray(); $formattedErrors = []; foreach ($errors as $field => $fieldErrors) { $formattedErrors[$field] = []; foreach ($fieldErrors as $errorItem) { // errorItem 此时是一个形如 ['en-CA' => '...', 'fr-CA' => '...'] 的数组 foreach ($errorItem as $locale => $message) { if (!isset($formattedErrors[$field][$locale])) { $formattedErrors[$field][$locale] = []; } $formattedErrors[$field][$locale][] = $message; } } } // 抛出包含自定义错误结构的HTTP响应异常 throw new HttpResponseException(response()->json([ 'detail' => $formattedErrors ], 422)); // 422 Unprocessable Entity 是常见的验证错误状态码 }}
代码解释:
$validator->getMessageBag()->toArray():获取原始的错误消息数组。$formattedErrors = []:初始化一个空数组,用于存储最终格式化的错误。外层foreach ($errors as $field => $fieldErrors):遍历每个发生错误的字段(例如email, first_name)。$fieldErrors是一个数组,其中包含该字段的所有错误消息项。内层foreach ($fieldErrors as $errorItem):遍历某个字段的每个具体错误。由于我们在messages()方法中定义了多语言结构,$errorItem现在是一个关联数组,键是语言代码,值是该语言的错误消息。最内层foreach ($errorItem as $locale => $message):遍历$errorItem中的每个语言及其对应的消息。$formattedErrors[$field][$locale][] = $message;:将消息添加到$formattedErrors中,按照字段 -> 语言 -> 消息数组的层级结构组织。throw new HttpResponseException(…):构建并抛出一个HttpResponseException,其中包含我们自定义的JSON响应结构。
完整示例代码
为了更清晰地展示,以下是整合后的ApiRequest和SysUserStoreRequest示例:
// app/Http/Requests/ApiRequest.phpnamespace AppHttpRequests;use IlluminateFoundationHttpFormRequest;use IlluminateContractsValidationValidator;use IlluminateHttpExceptionsHttpResponseException;abstract class ApiRequest extends FormRequest{ /** * Handle a failed validation attempt. * * @param IlluminateContractsValidationValidator $validator * @return void * * @throws IlluminateHttpExceptionsHttpResponseException */ protected function failedValidation(Validator $validator) { $errors = $validator->getMessageBag()->toArray(); $formattedErrors = []; foreach ($errors as $field => $fieldErrors) { $formattedErrors[$field] = []; foreach ($fieldErrors as $errorItem) { foreach ($errorItem as $locale => $message) { if (!isset($formattedErrors[$field][$locale])) { $formattedErrors[$field][$locale] = []; } $formattedErrors[$field][$locale][] = $message; } } } throw new HttpResponseException(response()->json([ 'detail' => $formattedErrors ], 422)); }}// app/Http/Requests/SysUserStoreRequest.phpnamespace AppHttpRequests;use AppHttpRequestsApiRequest; // 确保引入你的基类use IlluminateSupportFacadesLang; // 引入Lang门面class SysUserStoreRequest extends ApiRequest{ /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; // 根据你的授权逻辑设置 } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'email' => 'required|email|unique:users,email,' . ($this->id ?? 'NULL'), 'first_name' => 'required|string|min:5', // ... 其他字段规则 ]; } /** * Get the error messages for the defined validation rules. * * @return array */ public function messages() { return [ 'email.required' => [ 'en-CA' => Lang::get('validation.required', ['attribute' => Lang::get('portal.email', [], 'en-CA')],
以上就是在Laravel中实现多语言验证错误消息的并行展示的详细内容,更多请关注php中文网其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1338217.html
微信扫一扫
支付宝扫一扫