異常處理
系統產生的異常和錯誤都是程式的隱患,要儘早排除和解決,而不是掩蓋。對於應用自己丟擲的異常則做出相應的捕獲處理
我們在編寫程式碼的時候通常會使用流程語句,當然我們也可以把捕獲異常當成流程與就來使用
Tp在除錯模式下展示異常頁面,顯示具體細節,而在部署模式下,僅顯示錯誤資訊提示,這麼做是為了安全考慮。我們可以手動捕獲異常,如果工程量小的情況下可以,但是如果需要捕獲異常的地方有很多的話,豈不是要寫很多重複的程式碼,雖然利用公共方法可以解決重複問題,但這不是最優解。系統支援異常處理由開發者自定義類進行接管,需要在應用配置檔案app.php
中配置引數exception_handle
,下面就舉例Api介面的異常處理類。
配置異常處理handle類
在應用配置檔案app.php
'exception_handle' => 'app\common\exception\handler\ApiExceptionHandler',
定義異常基類
定義app\common\exception\BaseException.php
<?php
namespace app\common\exception;
use think\Exception;
class BaseException extends Exception
{
//http 狀態碼
public $code = 500;
//錯誤碼
public $errCode = 1000;
//錯誤訊息
public $errMsg = '伺服器內部錯誤';
public function __construct($error = [])
{
if( array_key_exists('code',$error) )
$this->code = $error['code'];
if( array_key_exists('errCode',$error) )
$this->errCode = $error['errCode'];
if( array_key_exists('errMsg',$error) )
$this->errMsg = $error['errMsg'];
}
}
定義異常處理Handle類
我們開發Api的時候,經常會驗證引數安全,以及手動丟擲可視性錯誤,那麼類似這些前端提示性錯誤可以直接返回前端,並且不需要記錄日誌。當然如果在開發除錯模式的話,可以交給系統處理異常,如果不是開發除錯模式,沒必要顯示具體的錯誤,比如返回給前端一大串英文錯誤資訊,客戶看了一臉懵逼,他也不知道具體錯在哪了,互動非常不好,因為客戶端根本不關心這些資訊。像這種情況,統一返回給客戶端提示說伺服器內部錯誤(大部分是我們程式碼的問題),然後記錄日誌,由後端人員再去檢查程式碼,處理好完備的邏輯。
定義app\common\exception\handler\ApiExceptionHandler.php
<?php
namespace app\common\exception\handler;
use app\common\exception\BaseException;
use Exception;
use think\exception\Handle;
use think\facade\Env;
use think\facade\Log;
class ApiExceptionHandler extends Handle
{
//http 狀態碼
private $code;
//錯誤訊息
private $errMsg;
//錯誤碼
private $errCode;
public function render(Exception $e)
{
//表示需要顯示具體錯誤訊息的異常類,並不需要記錄日誌
if($e instanceof BaseException){
$this->code = $e->code;
$this->errMsg = $e->errMsg;
$this->errCode = $e->errCode;
}else{
//獲取除錯資訊,如果處於除錯狀態,則顯示具體錯誤資訊,否則統一返回伺服器錯誤訊息,並記錄日誌
$appDebug = Env::get('app_debug',false);
//交給系統處理錯誤
if( $appDebug ){
return parent::render($e);
}
$this->code = 500;
$this->errCode = 9999;
$this->errMsg = '伺服器內部錯誤';
//記錄日誌
$this->recordLog($e);
}
$data = [
'msg' => $this->errMsg,
'code' => $this->errCode,
'data' => '',
];
return json()->data($data)->code($this->code);
}
/**
* 記錄錯誤日誌
* @param Exception $e
*/
public function recordLog(Exception $e)
{
$message = $e->getMessage();
Log::record($message,'error');
}
}
至此,異常處理已差不多完成,剩下的就是在實際邏輯中丟擲異常,就像上面說的類似流程控制似的,丟擲異常的時候就相當於終止了程式,返回給前端錯誤提示。