我們先來梳理一下異常的分類:
tp5 有一個(gè)全局異常處理類锥涕,如果我們想自己實(shí)現(xiàn)上面的分類艳悔,需要覆蓋和重寫默認(rèn)的全局異常處理類。
我們現(xiàn)在在 api 模塊的同級下新建一個(gè) lib 文件夾狗热,再新建一個(gè) exception 文件夾滤灯。
(我們想讓這個(gè) exception 里的類是一個(gè)通用的,可以供很多模塊使用的一個(gè)類庫忧饭。)
新建 ExceptionHandler 的 php class扛伍,并繼承 Handle 類。
<?php
namespace app\lib\exception;
use think\exception\Handle;
class ExceptionHandler extends Handle {
public function render(Exception $e){ // 重寫render方法
return json('~~~~~~~~~');
}
}
我們現(xiàn)在來驗(yàn)證一下是否會通過我們重寫的 ExceptionHandler 的 render 方法中的格式呈現(xiàn)異常眷昆。
在此之前蜒秤,我們先去掉(上)篇中的控制器自己處理的過程,將控制器還原為:
public function getBanner($id){
(new IDMustBePositiveInt())->goCheck();
$banner = BannerModel::getBannerByID($id);
return $banner;
}
并且重新指定 tp5 的全局異常處理類:
在 config.php 文件中的 'exception_handle'
字段輸入我們自定義的處理器的命名空間:
app\lib\exception\ExceptionHandler
用 postman 運(yùn)行后就可以看到 render 返回的值了亚斋。
現(xiàn)在我們繼續(xù)來寫 render 方法來區(qū)分前面提到的兩種異常:
其中有一種異常需要向客戶端返回具體信息作媚,我們需要新建一個(gè) BaseException 類:
<?php
namespace app\lib\exception;
class BaseException {
public $code = 400; // HTTP 狀態(tài)碼 404,200...
public $msg = '參數(shù)錯(cuò)誤'; // 錯(cuò)誤信息具體
public $errorCode = 10000; // 自定義錯(cuò)誤碼
}
這里的我們可以隨便寫,因?yàn)樽宇愬e(cuò)誤會將其覆蓋帅刊。
我們新建一個(gè) BannerMissException 的 php 類纸泡,繼承 BaseException。
比如說:
<?php
namespace app\lib\exception;
class BannerMissException extends BaseException
{
public $code = 404;
public $msg = '請求Banner不存在';
public $errorCode = 40000;
}
所以只要是繼承于 BaseException 的異常類都是我們自定義的類赖瞒,且需要返回給客戶端信息女揭。
我們這樣修改 render 方法:
private $code;
private $msg;
private $errorCode;
// 還需要返回客戶端當(dāng)前請求的URL地址
public function render(Exception $e){
if($e instanceof BaseException){
$this->code = $e->code;
$this->msg = $e->msg;
$this->errorCode = $e->errorCode;
} else {
$this->code = 500;
$this->msg = '服務(wù)器內(nèi)部異常';
$this->errorCode = 999;
}
$request = Request::instance();
$result=[
'msg' => $this->msg,
'error_code' => $this->errorCode,
'request_url' => $request->url()
];
return json($result,$this->code);
}
我們現(xiàn)在運(yùn)行后就會發(fā)現(xiàn):
我們下面來測試一下 BannerMissException蚤假,
將 model\Banner 中的 1/0 注釋掉,改為:
class Banner
{
public static function getBannerByID($id)
{
return null;
}
}
然后控制器里檢測一下拿到的 $banner
是否為空吧兔,因?yàn)?RESTFull 規(guī)則中規(guī)定獲取的值為空也是一種獲取不到資源的異常磷仰,所以我們?nèi)缦戮庉嬁刂破鞯拇a:
class Banner
{
public function getBanner($id)
{
(new IDMustBePositiveInt())->goCheck();
$banner = BannerModule::getBannerByID($id);
if (!$banner) {
throw new BannerMissException();
}
return $banner;
}
}
查看返回結(jié)果:
現(xiàn)在,我們記錄日志的要求還沒有實(shí)現(xiàn)境蔼,請看下一篇灶平。
tp5 API 自定義全局異常處理(下)