如何在 Laravel 5.1 中强制 FormRequest 返回 json?
我正在使用 FormRequest 来验证从我的 API 调用中发送的智能手机应用程序.所以,我希望 FormRequest 在验证失败时总是返回 json.
I'm using FormRequest to validate from which is sent in an API call from my smartphone app. So, I want FormRequest alway return json when validation fail.
看到如下Laravel框架的源码,如果reqeust是Ajax或者wantJson,FormRequest的默认行为是返回json.
I saw the following source code of Laravel framework, the default behaviour of FormRequest is return json if reqeust is Ajax or wantJson.
//IlluminateFoundationHttpFormRequest class
/**
* Get the proper failed validation response for the request.
*
* @param array $errors
* @return SymfonyComponentHttpFoundationResponse
*/
public function response(array $errors)
{
if ($this->ajax() || $this->wantsJson()) {
return new JsonResponse($errors, 422);
}
return $this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
}
我知道我可以在请求标头中添加 Accept= application/json
.FormRequest 将返回 json.但是我想提供一种更简单的方法来通过默认支持 json 来请求我的 API,而无需设置任何标头.所以,我试图在 IlluminateFoundationHttpFormRequest
类中找到一些强制 FormRequest 响应 json 的选项.但是我没有找到任何默认支持的选项.
I knew that I can add Accept= application/json
in request header. FormRequest will return json. But I want to provide an easier way to request my API by support json in default without setting any header. So, I tried to find some options to force FormRequest response json in IlluminateFoundationHttpFormRequest
class. But I didn't find any options which are supported in default.
我试图覆盖我的应用程序请求抽象类,如下所示:
I tried to overwrite my application request abstract class like followings:
<?php
namespace Laravel5CgHttpRequests;
use IlluminateFoundationHttpFormRequest;
use IlluminateHttpJsonResponse;
abstract class Request extends FormRequest
{
/**
* Force response json type when validation fails
* @var bool
*/
protected $forceJsonResponse = false;
/**
* Get the proper failed validation response for the request.
*
* @param array $errors
* @return SymfonyComponentHttpFoundationResponse
*/
public function response(array $errors)
{
if ($this->forceJsonResponse || $this->ajax() || $this->wantsJson()) {
return new JsonResponse($errors, 422);
}
return $this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
}
}
我添加了 protected $forceJsonResponse = false;
来设置我们是否需要强制响应 json.并且,在从 Request 抽象类扩展的每个 FormRequest 中.我设置了那个选项.
I added protected $forceJsonResponse = false;
to setting if we need to force response json or not. And, in each FormRequest which is extends from Request abstract class. I set that option.
例如:我创建了一个 StoreBlogPostRequest 并为此 FormRequest 设置了 $forceJsoResponse=true
并使其响应为 json.
Eg: I made an StoreBlogPostRequest and set $forceJsoResponse=true
for this FormRequest and make it response json.
<?php
namespace Laravel5CgHttpRequests;
use Laravel5CgHttpRequestsRequest;
class StoreBlogPostRequest extends Request
{
/**
* Force response json type when validation fails
* @var bool
*/
protected $forceJsonResponse = true;
/**
* 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|unique:posts|max:255',
'body' => 'required',
];
}
}
解决方案 2:添加中间件并强制更改请求标头
我构建了一个如下所示的中间件:
Solution 2: Add an Middleware and force change request header
I build a middleware like followings:
namespace Laravel5CgHttpMiddleware;
use Closure;
use SymfonyComponentHttpFoundationHeaderBag;
class AddJsonAcceptHeader
{
/**
* Add Json HTTP_ACCEPT header for an incoming request.
*
* @param IlluminateHttpRequest $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$request->server->set('HTTP_ACCEPT', 'application/json');
$request->headers = new HeaderBag($request->server->getHeaders());
return $next($request);
}
}
这是工作.但我想知道这个解决方案好吗?在这种情况下,是否有任何 Laravel 方式可以帮助我?
It 's work. But I wonder is this solutions good? And are there any Laravel Way to help me in this situation ?
推荐答案
我很奇怪为什么在 Laravel 中很难做到这一点.最后,根据你重写Request类的想法,我想出了这个.
It boggles my mind why this is so hard to do in Laravel. In the end, based on your idea to override the Request class, I came up with this.
app/Http/Requests/ApiRequest.php
<?php
namespace AppHttpRequests;
class ApiRequest extends Request
{
public function wantsJson()
{
return true;
}
}
然后,在每个控制器中只通过 AppHttpRequestsApiRequest
Then, in every controller just pass AppHttpRequestsApiRequest
公共函数索引(ApiRequest $request)
相关文章