PHP提供 Exception 類來處理異常
new Exception('錯誤信息(默認為空)','錯誤代碼(默認0)','異常鏈中前一個異常')
然后可以通過
e -> getMessage() 獲取異常信息 e -> getCode() 獲取異常錯誤碼
處理異常
try { //可能拋出異常代碼
throw new Exception("Error Processing Request", 1); } catch (Exception $e) { // 1. 記錄日志 // 2. 處理異常,程序繼續進行 / 繼續向上拋出異常 / 終止程序,打印異常錯誤
}
在ThinkPHP中,框架自帶異常處理類,返回錯誤信息以HTML頁面形式展示,如果程序出現錯誤開發人員沒有主動捕捉異常,則會被框架捕捉,然后拋出HTML
當在接口設計中時,由於無法得知客戶端類型,所以HTML的形式客戶端可能無法解析,此時便需要重寫異常類,以json的形式返回錯誤信息給客戶端
異常分類:
- 自定義異常:通常是由客戶端傳遞參數錯誤導致,此類異常不需要記錄日志,但需要返回錯誤原因
- 服務器異常:代碼錯誤導致異常,此類異常需要記錄日志,但不需要返回錯誤原因
服務器異常錯誤一般由PHP或者框架拋出,自定義異常需要手動捕捉,然后拋出
實現:
在Application/common目錄下新建 exception 目錄,此目錄為異常類庫目錄
Application/common/exception/ExceptionHandler (重寫后的異常處理類)
<?php namespace app\common\exception; use Exception; use think\exception\Handle; use think\facade\Request; use think\Log; class ExceptionHandler extends Handle { private $code; private $msg; private $errorCode; public function render(Exception $e) { if ($e instanceof BaseException) { //如果是自定義異常,則控制http狀態碼,不需要記錄日志 //因為這些通常是因為客戶端傳遞參數錯誤或者是用戶請求造成的異常 //不應當記錄日志
$this->code = $e->code; $this->msg = $e->msg; $this->errorCode = $e->errorCode; } else { // 如果是服務器未處理的異常,將http狀態碼設置為500,並記錄日志
if (config('app_debug')) { // 調試狀態下需要顯示TP默認的異常頁面,因為TP的默認頁面 // 很容易看出問題
return parent::render($e); } $this->code = 500; $this->msg = 'sorry,we make a mistake. (^o^)Y'; $this->errorCode = 999; $this->recordErrorLog($e); } $request = Request::instance(); $result = [ 'msg' => $this->msg,
'error_code' => $this->errorCode,
'request_url' => $request = $request->url(), ]; return json($result, $this->code); } /* * 將異常寫入日志 */
private function recordErrorLog(Exception $e) { Log::init([ 'type' => 'File',
'path' => LOG_PATH,
'level' => ['error'], ]); Log::record($e->getMessage(), 'error'); } }
這個類會判斷異常來源,並作出相應處理
創建處理類后,需要修改對應配置文件,讓這個類成為框架默認異常處理類
在application/config/app.php
// 異常處理handle類 留空使用 \think\exception\Handle
'exception_handle' => '\app\common\exception\ExceptionHandler',
Application/common/exception/BaseException (自定義異常類基類,基礎PHP自帶異常類Exception)
<?php namespace app\common\exception; use think\Exception; /** * Class BaseException * 自定義異常類的基類 */
class BaseException extends Exception { public $code = 400; public $msg = 'invalid parameters'; public $errorCode = 999; /** * 構造函數,接收一個關聯數組 * @param array $params 關聯數組只應包含code、msg和errorCode,且不應該是空值 */
public function __construct($params = []) { if (!is_array($params)) { return; } if (array_key_exists('code', $params)) { $this->code = $params['code']; } if (array_key_exists('msg', $params)) { $this->msg = $params['msg']; } if (array_key_exists('errorCode', $params)) { $this->errorCode = $params['errorCode']; } } }
自定義異常類
Application/common/exception/UserException (自定義異常,這里舉例User模塊的異常)
<?php namespace app\common\exception; class UserException extends BaseException { public $code = 404; public $msg = '用戶不存在'; public $errorCode = 60000; }
拋出自定義異常
try { //todo...
throw new \app\common\exception\UserException(); } catch (Exception $e) { }
此時異常展示不再是TP自帶的HTML頁,而是
{
"msg": "用戶不存在",
"error_code": 60000,
"request_url": "/wx_shop/public/index.php/admin/banner/list"
}