Mus*_*kat 8 php rest json laravel
我正在尝试使用Laravel Framework构建一个REST api,我想要一种方法来强制API始终使用JSON进行响应,而不是通过以下方式执行此操作:
return Response::json($data);
Run Code Online (Sandbox Code Playgroud)
换句话说,我希望每个响应都是JSON.有没有一个好方法呢?
更新:即使在未找到异常的异常情况下,响应也必须是JSON.
M16*_*437 24
按照Alexander Lichter 的建议创建一个中间件,为Accept每个请求设置标头:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ForceJsonResponse
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
Run Code Online (Sandbox Code Playgroud)
将它添加到$routeMiddleware了在app/Http/Kernel.php文件中:
protected $routeMiddleware = [
(...)
'json.response' => \App\Http\Middleware\ForceJsonResponse::class,
];
Run Code Online (Sandbox Code Playgroud)
您现在可以包装所有应返回 JSON 的路由:
Route::group(['middleware' => ['json.response']], function () { ... });
Run Code Online (Sandbox Code Playgroud)
让json.response中间件优先于其他中间件 -Authorize在设置Accept标头之前处理请求被其他中间件(例如中间件)终止的情况。
为此 - 用以下方法覆盖App\Http\Kernel类 ( app/Http/Kernel.php)的构造函数:
public function __construct( Application $app, Router $router ) {
parent::__construct( $app, $router );
$this->prependToMiddlewarePriority(\App\Http\Middleware\ForceJsonResponse::class);
}
Run Code Online (Sandbox Code Playgroud)
我知道这已得到解答,但这些都不是好的解决方案,因为它们以不可预测的方式更改状态代码。最好的解决方案是添加适当的标头,以便 Laravel 返回 JSON(我认为是它Accept: application/json),或者按照这个很棒的教程总是告诉 Laravel 返回 JSON:https ://hackernoon.com/always-return-json-with -laravel-api-870c46c5efb2
如果您想要更有选择性或适应更复杂的解决方案,您也可以通过中间件来做到这一点。
小智 9
我使用了这里提到的几种混合解决方案来解决所有问题,使其更加动态。原因是总是用 json 响应回复“/api”下面的每个请求。
app/Http/Middleware/ForceJsonResponse.php<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ForceJsonResponse
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// set Accept request header to application/json
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
Run Code Online (Sandbox Code Playgroud)
app/Http/Kernel.php protected $middlewareGroups = [
...
'api' => [
\App\Http\Middleware\ForceJsonResponse::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
...
];
Run Code Online (Sandbox Code Playgroud)
app/Exceptions/Handler.php namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
+ use Throwable;
class Handler extends ExceptionHandler
{
...
+ /**
+ * Render an exception into an HTTP response.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @param \Throwable $e
+ * @return \Illuminate\Http\Response
+ */
+ public function render($request, Throwable $e)
+ {
+ // Force to application/json rendering on API calls
+ if ($request->is('api*')) {
+ // set Accept request header to application/json
+ $request->headers->set('Accept', 'application/json');
+ }
+
+ // Default to the parent class' implementation of handler
+ return parent::render($request, $e);
+ }
}
Run Code Online (Sandbox Code Playgroud)
JsonResponseMiddleware中间件。
php artisan make:middleware JsonResponseMiddleware
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\ResponseFactory;
class JsonResponseMiddleware
{
/**
* @var ResponseFactory
*/
protected $responseFactory;
/**
* JsonResponseMiddleware constructor.
*/
public function __construct(ResponseFactory $responseFactory)
{
$this->responseFactory = $responseFactory;
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// First, set the header so any other middleware knows we're
// dealing with a should-be JSON response.
$request->headers->set('Accept', 'application/json');
// Get the response
$response = $next($request);
// If the response is not strictly a JsonResponse, we make it
if (!$response instanceof JsonResponse) {
$response = $this->responseFactory->json(
$response->content(),
$response->status(),
$response->headers->all()
);
}
return $response;
}
}
Run Code Online (Sandbox Code Playgroud)
App\Http\Kernel.phpprotected $middlewareGroups = [
'api' => [
...
....
/// Force to Json response (Our created Middleware)
\App\Http\Middleware\JsonResponseMiddleware::class,
],
'web' => [
...
....
/// Add Here as well if we want to force response in web routes too.
],
]
Run Code Online (Sandbox Code Playgroud)
现在我们将JSON只收到每个响应。
请注意:即使是异常也会以 JSON 格式响应
要JSON在控制器中返回return $data;
有关JSON错误的响应,请转到app\Exceptions\Handler.php文件并查看render方法.
你应该能够重写它看起来像这样:
public function render($request, Exception $e)
{
// turn $e into an array.
// this is sending status code of 500
// get headers from $request.
return response()->json($e, 500);
}
Run Code Online (Sandbox Code Playgroud)
但是你必须决定如何处理$e,因为它需要是一个array.您还可以设置状态代码和标题数组.
但是在任何错误的情况下,它都会返回JSON响应.
编辑:还可以注意到,您可以更改report方法以处理laravel如何记录错误.更多信息在这里.
| 归档时间: |
|
| 查看次数: |
5817 次 |
| 最近记录: |