本教程详细讲解如何在laravel应用中实现多语言验证错误消息的并行展示。通过重写formrequest的`messages`方法,为每个验证规则和字段定制多语言错误信息,并结合`failedvalidation`方法进行响应格式化,从而在单个api响应中同时返回不同语言的验证结果,满足复杂的国际化需求。
在构建国际化(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."
]
}
}
}要实现这种结构,我们需要在验证器生成错误消息的阶段就介入,而不是在消息生成完毕后尝试转换。
Laravel的FormRequest提供了一个messages()方法,允许开发者为每个验证规则和字段定制错误消息。这是在验证器生成MessageBag之前介入的关键点。通过在此方法中明确指定每种语言的错误消息,我们可以确保MessageBag在构建时就包含了所有必要的多语言信息。
首先,像往常一样在FormRequest中定义你的验证规则。例如:
// app/Http/Requests/SysUserStoreRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class SysUserStoreRequest extends ApiRequest // 假设ApiRequest是你的基类FormRequest
{
public function rules()
{
return [
'email' => 'required|email|unique:users,email,' . $this->id,
'first_name' => 'required|string|min:5',
// ... 其他字段规则
];
}
// ... 其他方法
}在SysUserStoreRequest中重写messages()方法,为每个字段和规则定义多语言错误信息。
// app/Http/Requests/SysUserStoreRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
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'),
],
// ... 为其他字段和规则添加类似的多语言消息
];
}
}代码解释:
通过这种方式,当验证失败时,Validator的MessageBag中,每个错误消息项将不再是简单的字符串,而是一个包含所有指定语言消息的数组。例如,$validator->getMessageBag()->toArray()可能会返回类似: ['email' => [['en-CA' => '...', 'fr-CA' => '...']]]
尽管messages()方法帮助我们生成了多语言数据,但MessageBag的默认结构可能不完全符合我们期望的最终JSON格式。我们需要在ApiRequest(或你的基础FormRequest类)中重写failedValidation方法,将MessageBag的内容转换为目标结构。
// app/Http/Requests/ApiRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
abstract class ApiRequest extends FormRequest
{
/**
* Handle a failed validation attempt.
*
* @param \Illuminate\Contracts\Validation\Validator $validator
* @return void
*
* @throws \Illuminate\Http\Exceptions\HttpResponseException
*/
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 是常见的验证错误状态码
}
}代码解释:
为了更清晰地展示,以下是整合后的ApiRequest和SysUserStoreRequest示例:
// app/Http/Requests/ApiRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
abstract class ApiRequest extends FormRequest
{
/**
* Handle a failed validation attempt.
*
* @param \Illuminate\Contracts\Validation\Val
idator $validator
* @return void
*
* @throws \Illuminate\Http\Exceptions\HttpResponseException
*/
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.php
namespace App\Http\Requests;
use App\Http\Requests\ApiRequest; // 确保引入你的基类
use Illuminate\Support\Facades\Lang; // 引入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')],
# php
# laravel
# js
# json
# cad
# app
# ai
# 多语言
# 状态码
# 本地化
# red
# 关联数组
# foreach
# throw
# 字符串
# Attribute
# 是一个
# 这是
# 重写
# 错误信息
# 遍历
# 自定义
# 抛出
# 法文
# 其中包含
相关文章:
C++如何编写函数模板?(泛型编程入门)
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
成都网站制作价格表,现在成都广电的单独网络宽带有多少的,资费是什么情况呢?
桂林网站制作公司有哪些,桂林马拉松怎么报名?
网站微信制作软件,如何制作微信链接?
建站168自助建站系统:快速模板定制与SEO优化指南
利用JavaScript实现拖拽改变元素大小
Python如何创建带属性的XML节点
制作销售网站教学视频,销售网站有哪些?
昆明高端网站制作公司,昆明公租房申请网上登录入口?
矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?
网站规划与制作是什么,电子商务网站系统规划的内容及步骤是什么?
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
如何选择建站程序?包含哪些必备功能与类型?
如何通过西部数码建站助手快速创建专业网站?
建站之星安装路径如何正确选择及配置?
北京制作网站的公司排名,北京三快科技有限公司是做什么?北京三快科技?
如何选择PHP开源工具快速搭建网站?
电脑免费海报制作网站推荐,招聘海报哪个网站多?
,网站推广常用方法?
高端云建站费用究竟需要多少预算?
官网建站费用明细查询_企业建站套餐价格及收费标准指南
我的世界制作壁纸网站下载,手机怎么换我的世界壁纸?
大连网站制作公司哪家好一点,大连买房网站哪个好?
如何在Golang中使用replace替换模块_指定本地或远程路径
宁波自助建站系统如何快速打造专业企业网站?
成都网站制作报价公司,成都工业用气开户费用?
如何用腾讯建站主机快速创建免费网站?
如何快速搭建FTP站点实现文件共享?
如何在橙子建站上传落地页?操作指南详解
可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?
建站之星备案流程有哪些注意事项?
娃派WAP自助建站:免费模板+移动优化,快速打造专业网站
建站主机是什么?如何选择适合的建站主机?
西安制作网站公司有哪些,西安货运司机用的最多的app或者网站是什么?
c++23 std::expected怎么用 c++优雅处理函数错误返回【详解】
江苏网站制作公司有哪些,江苏书法考级官方网站?
如何快速完成中国万网建站详细流程?
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
如何通过虚拟机搭建网站?详细步骤解析
建站之星如何配置系统实现高效建站?
如何在Golang中实现微服务服务拆分_Golang微服务拆分与接口管理方法
青岛网站建设如何选择本地服务器?
建站主机CVM配置优化、SEO策略与性能提升指南
小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?
黑客如何通过漏洞一步步攻陷网站服务器?
网站制作中优化长尾关键字挖掘的技巧,建一个视频网站需要多少钱?
如何快速辨别茅台真假?关键步骤解析
Avalonia如何实现跨窗口通信 Avalonia窗口间数据传递
如何快速配置高效服务器建站软件?
*请认真填写需求信息,我们会在24小时内与您取得联系。