tp5 針對對異常,在debug模式下,會直接以頁面返回的形式顯示出各類錯誤。如果debug關機,顯示
頁面錯誤!請稍后再試~
// 注冊錯誤和異常處理機制 Error::register();
self::getExceptionHandler()->render($e)->send()
getExceptionHandler()是判斷有沒有自定義的異常處理類,如果沒有默認使用namespace think\exception\Handle類處理異常(也就是tp5的默認處理方式)。
而我們可以在namespace think\App里的初始化函數定義了一個操作,如果配置里定義了自定義的異常處理類,那么就使用自定義異常處理類。也就是不用Handle類了。
大致思路是這樣,我們開始具體操作
首先我在 新建 namespace app\common\exception\ApiHandleException類
<?php
/**
* Created by PhpStorm.
* User: wangjing4
* Date: 2019-12-17
* Time: 9:19
*/
namespace app\common\exception;
use Exception;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\ErrorException;
use think\exception\PDOException;
use think\facade\Log;
class ApiHandleException extends Handle
{
public function render(Exception $e)
{
if( config('app_debug') ){
return parent::render($e);
}else{
$log['apiError'] = $this->getApiError($e);
$log['getData'] = $_GET;
$log['postData'] = $_POST;
$log['headerData'] = $_SERVER;
$re = $this->recordErrorLog($log);
if ($e instanceof HttpException) {
return json(array('msg'=>'請求錯誤','code'=> 400));
}
if ($e instanceof ErrorException) {
return json(array('msg'=>'返回異常','code'=> 500));
}
if ($e instanceof PDOException) {
return json(array('msg'=>"SQL異常",'code'=> 600));
}
}
}
private function getApiError($e){
$data = [];
if ($e instanceof HttpException) {
$data['msg'] = $e->getMessage();
}
if ($e instanceof ErrorException) {
$data['msg'] = $e->getMessage();
$data['file'] = $e->getFile();
$data['line'] = $e->getLine();
}
if ($e instanceof PDOException) {
$data['msg'] = $e->getData('Database Status');
}
return $data;
}
private function recordErrorLog($data)
{
Log::record($data,'error');
}
}
然后在配置文件里定義
'exception_handle' => '\app\common\exception\ApiHandleException',
這樣我們自己定義的這個類就接管異常處理了。
具體看下ApiHandleException類的思路。我們啟用新的異常處理類,其實最終就是要替換類里的render方法
所以新增render方法。首先ApiHandleException肯定要先繼承Handle類。當我們再debug模式的時候,大部分
是我們編寫接口的使用用postman類工具調試。此時tp5默認的拋出異常頁面挺適合我們查看錯誤的。所以就默認
啟用Handle里的render方法。而當上生產的時候,會關閉debug模式。此時我們就可以根據拋出的異常所屬類來
返回大致的消息
if ($e instanceof HttpException) {
return json(array('msg'=>'請求錯誤','code'=> 400));
}
if ($e instanceof ErrorException) {
return json(array('msg'=>'返回異常','code'=> 500));
}
if ($e instanceof PDOException) {
return json(array('msg'=>"SQL異常",'code'=> 600));
}
這幾個異常類型是我自己調試出來的。基本就這三種異常錯誤。
當你你訪問不存在的控制器或者方法的時候是會被 think\exception\HttpException;類拋出。
當頁面代碼有拼寫錯誤的時候,一般就是會think\exception\ErrorException報500錯誤。
而當sql語句問題導致的錯誤會被think\exception\PDOException拋出
生產環境需要記錄日志的時候,我使用了tp5的默認日志方法,根據不同報錯,保存了每種錯誤類型的基本信息,確保后端根據日志快速定位問題點。
比如HttpException錯誤;異常本身的錯誤提示基本就可以知道問題出在哪了。
而ErrorException可能就要定位到錯誤文件,錯誤的行數以及錯誤的提示語。
當遇到PDOException錯誤的時候,錯誤類默認記錄的PDO Error Info數據即可幫助我們快速知道錯誤sql
