?? Exception 異常插件

簡介
安裝
composer require tinywan/exception-handler
使用
配置
config/exception.php
return [
// 這里配置異常處理類
'' => \Tinywan\ExceptionHandler\Handler::class,
];
???? webman-admin 中配置
異常接管
/plugin/admin/config/exception.php
return [
'' => \Tinywan\ExceptionHandler\Handler::class,
];
接口不存在路由處理
/plugin/admin/config/route.php
Route::fallback(function () {
throw new \Tinywan\ExceptionHandler\Exception\RouteNotFoundException();
}, 'admin');
基本用法
請求參數(shù)錯誤
use support\Request;
use support\Response;
use Tinywan\ExceptionHandler\Exception\BadRequestHttpException;
class Token{
public function issueToken(Request $request): Response
{
$params = $request->post();
if (empty($params)) {
throw new BadRequestHttpException('賬號或密碼不能為空');
}
}
}
以上異常拋出錯誤信息,如下格式:
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=utf-8
{
"code": 0,
"msg": "賬號或密碼不能為空",
"data": {},
}
所有返回的異常信息將以json格式返回,以上為
返回簡略的異常信息
所有的異常錯誤處理器根據(jù)配置文件 config/app.php
中debug
的值來調整錯誤顯示, 當debug
值為true
(表示在調試模式), 錯誤處理器會顯示異常以及詳細的函數(shù)調用棧和源代碼行數(shù)來幫助調試,將返回詳細的異常信息。 當debug
值為false
,只有錯誤信息會被顯示以防止應用的敏感信息泄漏,將返回簡略的異常信息。
返回詳細的異常信息
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=utf-8
{
"code": 0,
"msg": "password不允許為空",
"data": {
"request_url": "POST //127.0.0.1:8888/oauth/issue-token",
"timestamp": "2022-03-06 15:19:12",
"client_ip": "172.18.0.1",
"request_param": {
"username": "webman"
},
"error_message": "password不允許為空",
"error_trace": "#0 /var/www/webman-admin/app/functions.php(68): Tinywan\\Validate\\Validate->check(Array)\n#1 /var/www/webman-admin/app/controller/Authentication.php(25): ..."
}
}
如何自定義一個自己的異常類
編寫異常類
假設自定義一個:405 Method Not Allowed
(表示:請求行中指定的請求方法不能被用于請求相應的資源)
自定義異常類只需要繼承Tinywan\ExceptionHandler\Exception\BaseException
類即可
<?php
declare(strict_types=1);
namespace support\exception;
use Tinywan\ExceptionHandler\Exception\BaseException;
class MethodNotAllowedException extends BaseException
{
/**
* @var int
*/
public $statusCode = 405;
/**
* @var string
*/
public $errorMessage = '請求行中指定的請求方法不能被用于請求相應的資源';
}
使用異常類
use support\Request;
use support\Response;
use support\exception\MethodNotAllowedException;
class Token{
public function issueToken(Request $request): Response
{
$params = $request->post();
if (empty($params)) {
throw new MethodNotAllowedException();
}
}
}
使用postman請求截圖
已支持插件異常類
- JWT 權限認證插件 異常類
JwtTokenException
- Validate 驗證器插件 異常類
ValidateException
內置異常類
- 客戶端異常類(HTTP Status 400):BadRequestHttpException
- 身份認證異常類(HTTP Status 401):UnauthorizedHttpException
- 資源授權異常類(HTTP Status 403):ForbiddenHttpException
- 資源不存在異常類(HTTP Status 404):NotFoundHttpException
- 路由地址不存在異常類(HTTP Status 404):RouteNotFoundException
- 請求限流在異常類(HTTP Status 429):TooManyRequestsHttpException
- 服務器內部錯誤異常類(HTTP Status 500):ServerErrorHttpException
HTTP 響應狀態(tài)碼
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
自定義異常 Response
只支持修改body
的三個字段的key值。必須保持順序是:
- ① 狀態(tài)碼
- ② 錯誤消息
- ③ 響應數(shù)據(jù)
使用場景
- 每個項目有標準的統(tǒng)一輸出,自定義返回內容
- 前后端分離:前端要求返回的
HTTP狀態(tài)碼
并不是429
,而是200
或者其他- 響應的
body
不是{"code":0,"msg":"Too Many Requests"}
,而是{"error_code":200,"message":"Too Many Requests"}
等其他內容
自定義HTTP狀態(tài)碼
編輯 config/plugin/tinywan/exception-handler/app.php
文件的 status
HTTP 狀態(tài)碼
自定義body
返回內容
編輯 config/plugin/tinywan/exception-handler/app.php
文件的 body
的字段
默認選項是
{
"code": 0,
"msg": "Too Many Requests",
"data": null
}
自定義選項參考一
1、假設status
HTTP 狀態(tài)碼設置為 200
2、假設body
的數(shù)組設為為
'body' => [
'error_code' => 200,
'message' => '請求太多請稍后重試'
]
則響應內容為
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"error_code": 200,
"message": "請求太多請稍后重試"
}
其他的可以根據(jù)自身業(yè)務自定義即可
擴展自己的 Handler
當項目需要自定義情況比較多的時候,很可能需要擴展 Handler,此時可以繼承 Tinywan\ExceptionHandler\Handler
然后修改對應方法即可。
使用場景
- response需要響應
xml
,而不是json格式,只需要覆蓋buildResponse
方法- 擴展其他Exception的響應,我只要覆蓋
solveExtraException
- 要異常推送微信消息,我可以覆蓋
triggerNotifyEvent
自定義異常 ErrorHandler
namespace support;
use Illuminate\Validation\ValidationException;
use Tinywan\ExceptionHandler\Handler;
use Webman\Http\Response;
class ErrorHandler extends Handler
{
/**
* @inheritDoc
*/
protected function solveExtraException(\Throwable $e): void
{
// 當前項目下的異常擴展
if ($e instanceof ValidationException) {
$this->errorMessage = $e->validator->errors()->first();
$this->errorCode = 422;
return;
}
parent::solveExtraException($e);
}
/**
* @inheritDoc
*/
protected function triggerNotifyEvent(\Throwable $e): void
{
// ... 這里省略觸發(fā)其他錯誤推送渠道
parent::triggerNotifyEvent($e);
}
/**
* @inheritDoc
*/
protected function buildResponse(): Response
{
// 構造自己項目下的響應
return json([
'code' => $this->statusCode, // 使用 statusCode 作為 code 返回
'msg' => $this->errorMessage,
'data' => $this->responseData,
]);
}
}