在 Laravel 5.4 中禁用请求验证重定向
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46350307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Disable request validation redirect in Laravel 5.4
提问by KeironLowe
So I'm trying to develop a rest API for an internal project, and I've got an issue where when the form request validation fails, it shows the @index response.
所以我正在尝试为一个内部项目开发一个 rest API,我遇到了一个问题,当表单请求验证失败时,它会显示 @index 响应。
So I have two routes;
所以我有两条路线;
Route::get('/api/clients', 'ClientController@index');
Route::post('/api/clients', 'ClientController@store');
@index
lists all clients, @store
creates a new client and I've got a Form Request Validator on the @store
method which checks a name is provided for the client.
@index
列出所有客户端,@store
创建一个新客户端,我在@store
检查为客户端提供名称的方法上有一个表单请求验证器。
What I want is when the validator fails, it shows a JSON response with the validation errors. But what I think it happening, is the validation fails, so it redirects back to the same page, but the redirect is GET
instead of POST
, so it lists all the clients instead.
我想要的是当验证器失败时,它会显示带有验证错误的 JSON 响应。但是我认为它发生的是验证失败,因此它重定向回同一页面,但重定向GET
不是POST
,因此它列出了所有客户端。
I know that you can set your headers so that it looks like an ajax request, in which it will show the JSON response properly, but I want it to show the JSON response regardless of whether it's ajax or not.
我知道你可以设置你的标题,使它看起来像一个 ajax 请求,它会正确显示 JSON 响应,但我希望它显示 JSON 响应,无论它是否是 ajax。
I've tried overriding the response
method in my validator which didn't work, I've tried setting the wantsJson
method in the validator to return true which again didn't work.
我试过response
在我的验证器中覆盖不起作用的wantsJson
方法,我试过将验证器中的方法设置为返回 true,这又不起作用。
Help would be very much appreciated.
非常感谢您的帮助。
Code is below...
代码如下...
web.php
网页.php
Route::get('/api/clients', 'ClientController@index');
Route::get('/api/clients/{client}', 'ClientController@show');
Route::post('/api/clients', 'ClientController@store');
Route::put('/api/clients/{id}', 'ClientController@update');
Route::delete('/api/clients/{id}', 'ClientController@delete');
ClientController.php
客户端控制器.php
namespace App\Http\Controllers;
use App\Client;
use App\Http\Requests\ClientRequest;
class ClientController extends Controller
{
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(ClientRequest $request)
{
return Client::create([
'title' => request('title'),
'user_id' => auth()->id()
]);
}
ClientRequest.php
客户端请求.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ClientRequest extends FormRequest
{
/**
* 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 [
'title' => 'required'
];
}
/**
* Get the failed validation response for the request.
*
* @param array $errors
* @return JsonResponse
*/
public function response(array $errors)
{
dd('exit'); // Doesn't work
}
}
回答by iCoders
You can try like this
你可以这样试试
Include use first as below in your form request
在您的表单请求中首先包括如下使用
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
and then
进而
protected function failedValidation(Validator $validator) {
throw new HttpResponseException(response()->json($validator->errors(), 422));
}
now if you try to validate then it will return like
现在,如果您尝试验证,那么它会像
{
"title": [
"The title field is required."
]
}
回答by Christophvh
When making the request we should send header info.
发出请求时,我们应该发送标头信息。
Accept: application/json
Content-Type: application/json
That's it, now laravel will not redirect and send the error message as JSON.
就是这样,现在 laravel 不会重定向并将错误消息作为 JSON 发送。
回答by Dmitry Guzun
Try this
尝试这个
Open app/Exceptions/Handler.php file
打开 app/Exceptions/Handler.php 文件
Include use
包括使用
use Illuminate\Validation\ValidationException;
and then add method
然后添加方法
/**
* Create a response object from the given validation exception.
*
* @param \Illuminate\Validation\ValidationException $e
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function convertValidationExceptionToResponse(ValidationException $e, $request)
{
if ($e->response) {
return $e->response;
}
return response()->json($e->validator->errors()->getMessages(), 422);
}
now you can get standard validationFailure response like ajax request
现在您可以获得标准的validationFailure 响应,如ajax 请求
回答by RousseauAlexandre
I just created a ApiFormRequest
who override FormRequest::failedValidation
method like this:
我刚刚创建了一个像这样的ApiFormRequest
who overrideFormRequest::failedValidation
方法:
<?php
// app/Http/Requests/ApiFormRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;
class ApiFormRequest extends FormRequest
{
protected function failedValidation(Validator $validator): void
{
$jsonResponse = response()->json(['errors' => $validator->errors()], 422);
throw new HttpResponseException($jsonResponse);
}
}
Then you simply use like this
然后你只需像这样使用
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ClientRequest extends ApiFormRequest
{
// ...
回答by Attila Szeremi
I made a middleware (for API requests only) to make the Accept header include application/json by default:
我制作了一个中间件(仅适用于 API 请求)以使 Accept 标头默认包含 application/json:
/**
* Ensures the default Accept header is application/json
*/
class DefaultApiAcceptJson
{
public function handle(Request $request, \Closure $next)
{
$acceptHeader = $request->headers->get('Accept');
if (!Str::contains($acceptHeader, 'application/json')) {
$newAcceptHeader = 'application/json';
if ($acceptHeader) {
$newAcceptHeader .= "/$acceptHeader";
}
$request->headers->set('Accept', $newAcceptHeader);
}
return $next($request);
}
}
This way I always get the validation error JSON response rather than a redirect to the web index page.
这样我总是得到验证错误 JSON 响应,而不是重定向到 Web 索引页面。
回答by Amin Shojaei
There is two waysto work with validator errors, my suggestion is second way:
有两种方法可以处理验证器错误,我的建议是第二种方法:
1.First way, Simply return an error when validation fail's(in controller). Example:
1.第一种方法,当验证失败时(在控制器中)简单地返回一个错误。例子:
try {
request()->validate([
'input1' => 'required',
'input2' => 'string|min:5',
]);
} catch (\Illuminate\Validation\ValidationException $e){
return response('The given data was invalid.', 400);
}
Handy and clean.
方便又干净。
2.Second way is show full errors to user(in controller), like this:
2.第二种方式是向用户(在控制器中)显示完整错误,如下所示:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(request()->all(), [
'id' => 'required|integer',
'description' => 'string'
]);
// return array of errors to client with status code 400
if ($validator->fails())
return response($validator->messages()->toArray(), 400);
回答by Fatalist
Simply use this trait to prevent redirect after FormRequest
validation.
The following trait is also brings some useful public methods, such as:
只需使用此特征来防止FormRequest
验证后重定向。以下 trait 也带来了一些有用的公共方法,例如:
validatorPasses()
validatorFails()
validatorErrors()
respondWithErrorsJson(int $code = 422)
redirectWithErrors()
- restores the default Laravel FomrRequest behavior
validatorPasses()
validatorFails()
validatorErrors()
respondWithErrorsJson(int $code = 422)
redirectWithErrors()
- 恢复默认的 Laravel FormrRequest 行为
Trait
特征
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\MessageBag;
use Illuminate\Validation\ValidationException;
trait PreventsRedirectWhenFailedTrait
{
/**
* Default self::failedValidation() Laravel behavior flag.
*
* @var bool
*/
private $defaultFailedValidationRestored = false;
/**
* Check for validator success flag.
*
* @return bool
*/
public function validatorPasses(): bool
{
return !$this->validatorFails();
}
/**
* Check for validator fail flag.
*
* @return bool
*/
public function validatorFails(): bool
{
return $this->getValidatorInstance()->fails();
}
/**
* @return MessageBag
*/
public function validatorErrors(): MessageBag
{
return $this->getValidatorInstance()->errors();
}
/**
* Respond with validator errors in JSON format.
*
* @param int $code
*/
public function respondWithErrorsJson(int $code = 422): void
{
if ($this->validatorFails()) {
throw new HttpResponseException(
response()->json(['errors' => $this->getValidatorInstance()->errors()], $code)
);
}
}
/**
* Restore and apply default self::failedValidation() method behavior.
*
* @throws ValidationException
*/
public function redirectWithErrors(): void
{
$this->defaultFailedValidationRestored = true;
$this->failedValidation($this->getValidatorInstance());
}
/**
* Handle a failed validation attempt.
*
* @param \Illuminate\Contracts\Validation\Validator $validator
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*/
protected function failedValidation(Validator $validator): void
{
if ($this->defaultFailedValidationRestored) {
throw (new ValidationException($validator))
->errorBag($this->errorBag)
->redirectTo($this->getRedirectUrl());
}
}
}
Usage example:
用法示例:
namespace App\Http\Requests;
use Auth;
use Illuminate\Foundation\Http\FormRequest;
class AuthRequest extends FormRequest
{
use PreventsRedirectWhenFailedTrait;
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize(): bool
{
return Auth::guest();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [
'email' => 'required|email|exists:users',
'password' => 'required',
'remember_me' => 'integer',
];
}
}
Inside your controller:
在您的控制器内部:
public function authenticate(AuthRequest $request)
{
if ($request->validatorPasses()) {
$data = $request->validated();
/* your logic */
} else {
$errorBag = $request->validatorErrors();
}
// or
if ($request->validatorFails()) {
// your logic
}
}
Hope you'll find this helpful.
希望你会发现这有帮助。