在 Laravel 中发送来自验证器的自定义响应
Send custom response from validator in Laravel
我有一个使用 name
、email
和 password
的注册用户路由。如果数据正确,即存在唯一的电子邮件和参数,它工作得很好,但如果用户已经注册,则 Laravel 以其自己的格式发送自动错误消息。我希望 return 格式在成功或失败的情况下保持一致。
注册成功return数据:
{
"status": "success",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjUsImlzcyI6Imh0dHA6Ly8xMjcuMC4wLjE6ODAwMC9hcGkvYXV0aC9yZWdpc3RlciIsImlhdCI6MTUyMTI3NTc5MiwiZXhwIjoxNTIxMjc5MzkyLCJuYmYiOjE1MjEyNzU3OTIsImp0aSI6Ik1wSzJSYmZYU1dobU5UR0gifQ.fdajaDooBTwP-GRlFmAu1gtC7_3U4ygD1TSBIqdPHf0"
}
但如果出现错误,它会以其他格式发送数据。
{"message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}
我希望两者保持一致。成功return 数据正常。但如果发生故障,我想自定义数据。像这样:
{"status":"error","message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}
基本上,我需要 status
参数随每个响应一起出现。
此外,我在使用 Postman 时有一个查询输出是纯 HTML 当错误发生时 HTML 页面是默认的 Laravel 页面另一方面当 angular 发送相同的请求错误是我刚刚粘贴在上面的 json 格式。
由于 angular 得到 JSON 响应,无论如何这对我来说都很好。但是邮递员为什么不给我看那个回复。
注册控制器:
public function register(RegisterRequest $request)
{
$newUser = $this->user->create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => bcrypt($request->get('password'))
]);
if (!$newUser) {
return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
}
return response()->json([
'status' => 'success',
'token' => $this->jwtauth->fromUser($newUser)
]);
}
注册请求处理程序:
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required',
'email' => 'required | email | unique:users,email',
'password' => 'required'
];
}
如果我没理解错的话,你得到的总是 error-response 而没有 'status' 键。
您当前的代码发生了什么,有以下几点:
- RegisterController@register(RegisterRequest $request) 被路由调用
- Laravel 看到您使用 RegisterRequest class 作为参数,并将为您实例化此 class。
- 实例化此 class 意味着它将直接验证规则。
- 如果不符合规则,laravel直接响应发现的错误。
- 此响应将始终采用 laravel 的默认值 'layout',代码到此为止。
结论:当您的验证规则不符合时,您的代码甚至不会被触发。
我研究了一个解决方案并提出了这个:
public function register(Illuminate\Http\Request $request)
{
//Define your validation rules here.
$rules = [
'name' => 'required',
'email' => 'required | email | unique:users,email',
'password' => 'required'
];
//Create a validator, unlike $this->validate(), this does not automatically redirect on failure, leaving the final control to you :)
$validated = Illuminate\Support\Facades\Validator::make($request->all(), $rules);
//Check if the validation failed, return your custom formatted code here.
if($validated->fails())
{
return response()->json(['status' => 'error', 'messages' => 'The given data was invalid.', 'errors' => $validated->errors()]);
}
//If not failed, the code will reach here
$newUser = $this->user->create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => bcrypt($request->get('password'))
]);
//This would be your own error response, not linked to validation
if (!$newUser) {
return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
}
//All went well
return response()->json([
'status' => 'success',
'token' => $this->jwtauth->fromUser($newUser)
]);
}
现在,不符合您的验证规则仍然会触发错误,但是您的错误,而不是 laravel 的 built-in 错误:)
希望对您有所帮助!
这是我想出的:
function validate(array $rules)
{
$validator = Validator::make(request()->all(), $rules);
$errors = (new \Illuminate\Validation\ValidationException($validator))->errors();
if ($validator->fails()) {
throw new \Illuminate\Http\Exceptions\HttpResponseException(response()->json(
[
'status' => false,
'message' => "Some fields are missing!",
'error_code' => 1,
'errors' => $errors,
], \Illuminate\Http\JsonResponse::HTTP_UNPROCESSABLE_ENTITY));
}
}
创建帮助程序目录 (App\Helpers
) 并将其添加到文件中。不要忘记将其添加到您的 composer.json
"autoload": {
"files": [
"app/Helpers/system.php",
],
},
现在您可以在您的控制器中调用 validate()
并获得您想要的:
validate([
'email' => 'required|email',
'password' => 'required|min:6|max:32',
'remember' => 'nullable|boolean',
'captcha' => 'prod_required|hcaptcha',
]);
在 Laravel 8 中,我添加了带有“成功”的自定义 invalidJson:false:
在 app/Exceptions/Handler.php:
/**
* Convert a validation exception into a JSON response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Validation\ValidationException $exception
* @return \Illuminate\Http\JsonResponse
*/
protected function invalidJson($request, ValidationException $exception)
{
return response()->json([
'success' => false,
'message' => $exception->getMessage(),
'errors' => $exception->errors(),
], $exception->status);
}
我有一个使用 name
、email
和 password
的注册用户路由。如果数据正确,即存在唯一的电子邮件和参数,它工作得很好,但如果用户已经注册,则 Laravel 以其自己的格式发送自动错误消息。我希望 return 格式在成功或失败的情况下保持一致。
注册成功return数据:
{
"status": "success",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjUsImlzcyI6Imh0dHA6Ly8xMjcuMC4wLjE6ODAwMC9hcGkvYXV0aC9yZWdpc3RlciIsImlhdCI6MTUyMTI3NTc5MiwiZXhwIjoxNTIxMjc5MzkyLCJuYmYiOjE1MjEyNzU3OTIsImp0aSI6Ik1wSzJSYmZYU1dobU5UR0gifQ.fdajaDooBTwP-GRlFmAu1gtC7_3U4ygD1TSBIqdPHf0"
}
但如果出现错误,它会以其他格式发送数据。
{"message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}
我希望两者保持一致。成功return 数据正常。但如果发生故障,我想自定义数据。像这样:
{"status":"error","message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}
基本上,我需要 status
参数随每个响应一起出现。
此外,我在使用 Postman 时有一个查询输出是纯 HTML 当错误发生时 HTML 页面是默认的 Laravel 页面另一方面当 angular 发送相同的请求错误是我刚刚粘贴在上面的 json 格式。 由于 angular 得到 JSON 响应,无论如何这对我来说都很好。但是邮递员为什么不给我看那个回复。
注册控制器:
public function register(RegisterRequest $request)
{
$newUser = $this->user->create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => bcrypt($request->get('password'))
]);
if (!$newUser) {
return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
}
return response()->json([
'status' => 'success',
'token' => $this->jwtauth->fromUser($newUser)
]);
}
注册请求处理程序:
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required',
'email' => 'required | email | unique:users,email',
'password' => 'required'
];
}
如果我没理解错的话,你得到的总是 error-response 而没有 'status' 键。
您当前的代码发生了什么,有以下几点:
- RegisterController@register(RegisterRequest $request) 被路由调用
- Laravel 看到您使用 RegisterRequest class 作为参数,并将为您实例化此 class。
- 实例化此 class 意味着它将直接验证规则。
- 如果不符合规则,laravel直接响应发现的错误。
- 此响应将始终采用 laravel 的默认值 'layout',代码到此为止。
结论:当您的验证规则不符合时,您的代码甚至不会被触发。
我研究了一个解决方案并提出了这个:
public function register(Illuminate\Http\Request $request)
{
//Define your validation rules here.
$rules = [
'name' => 'required',
'email' => 'required | email | unique:users,email',
'password' => 'required'
];
//Create a validator, unlike $this->validate(), this does not automatically redirect on failure, leaving the final control to you :)
$validated = Illuminate\Support\Facades\Validator::make($request->all(), $rules);
//Check if the validation failed, return your custom formatted code here.
if($validated->fails())
{
return response()->json(['status' => 'error', 'messages' => 'The given data was invalid.', 'errors' => $validated->errors()]);
}
//If not failed, the code will reach here
$newUser = $this->user->create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => bcrypt($request->get('password'))
]);
//This would be your own error response, not linked to validation
if (!$newUser) {
return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
}
//All went well
return response()->json([
'status' => 'success',
'token' => $this->jwtauth->fromUser($newUser)
]);
}
现在,不符合您的验证规则仍然会触发错误,但是您的错误,而不是 laravel 的 built-in 错误:)
希望对您有所帮助!
这是我想出的:
function validate(array $rules)
{
$validator = Validator::make(request()->all(), $rules);
$errors = (new \Illuminate\Validation\ValidationException($validator))->errors();
if ($validator->fails()) {
throw new \Illuminate\Http\Exceptions\HttpResponseException(response()->json(
[
'status' => false,
'message' => "Some fields are missing!",
'error_code' => 1,
'errors' => $errors,
], \Illuminate\Http\JsonResponse::HTTP_UNPROCESSABLE_ENTITY));
}
}
创建帮助程序目录 (App\Helpers
) 并将其添加到文件中。不要忘记将其添加到您的 composer.json
"autoload": {
"files": [
"app/Helpers/system.php",
],
},
现在您可以在您的控制器中调用 validate()
并获得您想要的:
validate([
'email' => 'required|email',
'password' => 'required|min:6|max:32',
'remember' => 'nullable|boolean',
'captcha' => 'prod_required|hcaptcha',
]);
在 Laravel 8 中,我添加了带有“成功”的自定义 invalidJson:false:
在 app/Exceptions/Handler.php:
/**
* Convert a validation exception into a JSON response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Validation\ValidationException $exception
* @return \Illuminate\Http\JsonResponse
*/
protected function invalidJson($request, ValidationException $exception)
{
return response()->json([
'success' => false,
'message' => $exception->getMessage(),
'errors' => $exception->errors(),
], $exception->status);
}