Laravel如何實(shí)現(xiàn)適合Api的異常處理響應(yīng)格式
前言
Laravel全局捕獲異常后,會(huì)把異常轉(zhuǎn)為相應(yīng)的數(shù)據(jù)格式返回給用戶。如果想要規(guī)定的數(shù)據(jù)格式相應(yīng),那我們只需重寫異常捕獲后的處理方法即可。
異常處理流程
Illuminate\Foundation\Exception\Handler 中的 render 方法用來將異常轉(zhuǎn)化為響應(yīng)。
public function render($request, Exception $e)
{
if (method_exists($e, 'render') && $response = $e->render($request)) {
return Router::toResponse($request, $response);
} elseif ($e instanceof Responsable) {
return $e->toResponse($request);
}
$e = $this->prepareException($e);
if ($e instanceof HttpResponseException) {
return $e->getResponse();
} elseif ($e instanceof AuthenticationException) {
return $this->unauthenticated($request, $e);
} elseif ($e instanceof ValidationException) {
return $this->convertValidationExceptionToResponse($e, $request);
}
return $request->expectsJson()
? $this->prepareJsonResponse($request, $e)
: $this->prepareResponse($request, $e);
}
render() 中又調(diào)用了 prepareException() 對(duì)部分異常進(jìn)行預(yù)處理,但并未執(zhí)行轉(zhuǎn)化為響應(yīng)的操作。
ModelNotFoundException 一般在模型查找不到拋出,prepareException() 中它被轉(zhuǎn)為 Symfony 包中NotFoundHttpException,默認(rèn)狀態(tài)碼404;
AuthorizationException 在 Policy 權(quán)限未通過時(shí)拋出,prepareException() 中它被轉(zhuǎn)為 Symfony 包中 AccessDeniedHttpException,默認(rèn)狀態(tài)碼403;
TokenMismatchException 在 CSRF 驗(yàn)證未通過時(shí)拋出,prepareException() 中它被轉(zhuǎn)為 Symfony 包中 HttpException,給定狀態(tài)碼419;
其他異常直接返回。
protected function prepareException(Exception $e)
{
if ($e instanceof ModelNotFoundException) {
$e = new NotFoundHttpException($e->getMessage(), $e);
} elseif ($e instanceof AuthorizationException) {
$e = new AccessDeniedHttpException($e->getMessage(), $e);
} elseif ($e instanceof TokenMismatchException) {
$e = new HttpException(419, $e->getMessage(), $e);
}
return $e;
}
在回到 render() ,預(yù)處理異常之后,又分別對(duì) HttpResponseException、AuthenticationException 和 ValidationException 單獨(dú)處理,并轉(zhuǎn)為響應(yīng)返回。
除此以外的異常,都在 prepareJsonResponse() 或 prepareResponse() 處理 ,expectsJson() 用來判斷返回 json 響應(yīng)還是普通響應(yīng)。
修改異常響應(yīng)格式
了解了異常處理流程,接下來就處理異常響應(yīng)格式。
修改登錄認(rèn)證異常格式
由上文可知,AuthenticationException 被捕獲后,調(diào)用 unauthenticated() 來處理。
protected function unauthenticated($request, AuthenticationException $exception)
{
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest($exception->redirectTo() ?? route('login'));
}
在 appExceptionsHandler.php 中重寫 unauthenticated() 使其返回我們想要的數(shù)據(jù)格式。
protected function unauthenticated($request, AuthenticationException $exception)
{
return $request->expectsJson()
? response()->json([
'code' => 0,
'data' => $exception->getMessage(),
], 401)
: redirect()->guest($exception->redirectTo() ?? route('login'));
}
修改驗(yàn)證異常格式
同樣由上文可知,ValidationException 被捕獲后交由 convertValidationExceptionToResponse() 處理,進(jìn)入此方法后我們需要繼續(xù)追蹤,若是需要 json 響應(yīng),最終交由 invalidJson() 處理。
protected function convertValidationExceptionToResponse(ValidationException $e, $request)
{
if ($e->response) {
return $e->response;
}
return $request->expectsJson()
? $this->invalidJson($request, $e)
: $this->invalid($request, $e);
}
protected function invalidJson($request, ValidationException $exception)
{
return response()->json([
'message' => $exception->getMessage(),
'errors' => $exception->errors(),
], $exception->status);
}
我們繼續(xù)在 appExceptionsHandler.php 重寫 invalidJson() 即可自定義返回格式。
protected function invalidJson($request, ValidationException $exception)
{
return response()->json([
'code' => 0,
'data' => $exception->errors(),
], $exception->status);
}
修改其他異常格式
其他異常是調(diào)用 prepareJsonResponse() 來處理,此方法又調(diào)用 convertExceptionToArray() 來處理響應(yīng)格式。
protected function prepareJsonResponse($request, Exception $e)
{
return new JsonResponse(
$this->convertExceptionToArray($e),
$this->isHttpException($e) ? $e->getStatusCode() : 500,
$this->isHttpException($e) ? $e->getHeaders() : [],
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
);
}
protected function convertExceptionToArray(Exception $e)
{
return config('app.debug') ? [
'message' => $e->getMessage(),
'exception' => get_class($e),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => collect($e->getTrace())->map(function ($trace) {
return Arr::except($trace, ['args']);
})->all(),
] : [
'message' => $this->isHttpException($e) ? $e->getMessage() : 'Server Error',
];
}
在 appExceptionsHandler.php 中重寫 convertExceptionToArray() 來自定義其他異常響應(yīng)格式。
protected function convertExceptionToArray(Exception $e)
{
return config('app.debug') ? [
'code' => 0,
'data' => $e->getMessage(),
'exception' => get_class($e),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => collect($e->getTrace())->map(function ($trace) {
return Arr::except($trace, ['args']);
})->all(),
] : [
'code' => 0,
'data' => $this->isHttpException($e) ? $e->getMessage() : 'Server Error',
];
}
強(qiáng)制 json 響應(yīng)
代碼中多次出現(xiàn)了 expectsJson() ,此方法是用來判斷返回 json 響應(yīng)還是普通響應(yīng)。
public function expectsJson()
{
return ($this->ajax() && ! $this->pjax() && $this->acceptsAnyContentType()) || $this->wantsJson();
}
以下兩種條件下,會(huì)返回json響應(yīng)。
非XML請(qǐng)求、非pjax并且 Headers 中 Accept 設(shè)置為接收所有格式響應(yīng);
Headers Accept 設(shè)置為 /json、+json。如:Accept:application/json。
除此之外的情況,將不會(huì)響應(yīng)json。我們可以利用中間件強(qiáng)制追加 Accept:application/json,使異常響應(yīng)時(shí)都返回json。(參考教程 L03 6.0 中提到的方法)
創(chuàng)建中間件 AcceptHeader
<?php
namespace App\Http\Middleware;
use Closure;
class AcceptHeader
{
public function handle($request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
在 app/Http/Kernel.php 中,將中間件加入路由組即可。
protected $middlewareGroups = [ 'web' => [ . . . 'api' => [ \App\Http\Middleware\AcceptHeader::class, 'throttle:60,1', 'bindings', ], ];
大功告成。
總結(jié)
到此這篇關(guān)于Laravel如何實(shí)現(xiàn)適合Api的異常處理響應(yīng)格式的文章就介紹到這了,更多相關(guān)Laravel適合Api的異常處理響應(yīng)格式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解Laravel制作API接口
- 在 Laravel 中動(dòng)態(tài)隱藏 API 字段的方法
- Laravel實(shí)現(xiàn)ApiToken認(rèn)證請(qǐng)求
- laravel框架 api自定義全局異常處理方法
- laravel dingo API返回自定義錯(cuò)誤信息的實(shí)例
- Laravel框架實(shí)現(xiàn)調(diào)用百度翻譯API功能示例
- PHP使Laravel為JSON REST API返回自定義錯(cuò)誤的問題
- 讓Laravel API永遠(yuǎn)返回JSON格式響應(yīng)的方法示例
- Larave框架通過sanctum進(jìn)行API鑒權(quán)詳解
相關(guān)文章
php遠(yuǎn)程請(qǐng)求CURL實(shí)例教程(爬蟲、保存登錄狀態(tài))
這篇文章主要給大家介紹了關(guān)于php遠(yuǎn)程請(qǐng)求CURL(爬蟲、保存登錄狀態(tài))的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Yii2中OAuth擴(kuò)展及QQ互聯(lián)登錄實(shí)現(xiàn)方法
這篇文章主要介紹了Yii2中OAuth擴(kuò)展及QQ互聯(lián)登錄的方法,實(shí)例分析了OAuth擴(kuò)展的相關(guān)配置與QQ互聯(lián)登陸的實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-05-05
詳解PHP實(shí)現(xiàn)支付寶小程序用戶授權(quán)的工具類
這篇文章主要介紹了詳解PHP實(shí)現(xiàn)支付寶小程序用戶授權(quán)的工具類,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12
PHP 閉包獲取外部變量和global關(guān)鍵字聲明變量的區(qū)別講解
閉包是一個(gè)常見的概念,我們通??梢詫⑵渑c回調(diào)函數(shù)配合使用,可以使代碼更加簡(jiǎn)潔易讀。這篇文章主要介紹了PHP 閉包獲取外部變量和global關(guān)鍵字聲明變量的區(qū)別,需要的朋友可以參考下2017-12-12
PHP對(duì)接微信公眾平臺(tái)消息接口開發(fā)流程教程
這篇文章主要介紹了PHP對(duì)接微信公眾平臺(tái)消息接口開發(fā)流程,如何使用PHP版接口操作公眾平臺(tái)消息,需要的朋友可以參考下2014-03-03
Zend Framework教程之連接數(shù)據(jù)庫并執(zhí)行增刪查的方法(附demo源碼下載)
這篇文章主要介紹了Zend Framework教程之連接數(shù)據(jù)庫并執(zhí)行增刪查的方法,結(jié)合實(shí)例形式詳細(xì)分析了Zend Framework數(shù)據(jù)庫的配置及執(zhí)行增刪改查等操作的相關(guān)實(shí)現(xiàn)方法,需要的朋友可以參考下2016-03-03
PHP 進(jìn)程池與輪詢調(diào)度算法實(shí)現(xiàn)多任務(wù)的示例代碼
這篇文章主要介紹了PHP 進(jìn)程池與輪詢調(diào)度算法實(shí)現(xiàn)多任務(wù)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11

