一、固有思維模式
目錄結構
//banner控制器
<?php
namespace app\api\controller\v1;
use app\api\validate\IDMustBePostiveInt;
use app\api\model\Banner as BannerModel;
use think\Exception;
class Banner
{
public function getBanner($id){
(new IDMustBePostiveInt()) -> goCheck();
try{
$banner = BannerModel::getBannerById($id);
return $banner;
}catch (Exception $ex){
$error = [
'error_code' => 10001,
'msg' => $ex -> getMessage()
];
return json($error, 400);
}
}
}
//mode Banner
<?php
namespace app\api\model;
use think\Exception;
class Banner
{
public static function getBannerById($id)
{
try{
1/0;
}catch (Exception $ex){
throw $ex;
}
return 'this is banner info';
}
}
//驗證層 基類
<?php
namespace app\api\validate;
use think\Exception;
use think\Request;
use think\Validate;
class BaseValidate extends Validate
{
public function goCheck(){
//獲取http傳入的參數
//對這些參數做校驗
$request = Request::instance();
$params = $request -> param();
$result = $this -> check($params);
if(!$result){
$error = $this->getError();
throw new Exception($error);
}else{
return true;
}
}
}
//驗證層 id必須爲正整數
<?php
namespace app\api\validate;
class IDMustBePostiveInt extends BaseValidate
{
protected $rule = [
'id' => 'require|isPostiveInteger'
];
//field是字段名
protected function isPostiveInteger($value, $rule = '', $data = '', $field = ''){
if(is_numeric($value) && is_int($value + 0) && ($value + 0) > 0){
return true;
}else{
return $field.'必須是正整數';
}
}
}
二、總結異常分類
1、由於用戶行爲導致的異常(沒有通過驗證器,沒有查詢到結果)
通常不需要記錄日誌 需要向用戶返回具體信息
2、服務器自身異常(代碼錯誤、調用外部接口異常)
通常記錄日誌 不向用戶返回具體信息
三、自定義全局異常處理
目錄結構
//控制器 Banner
<?php
namespace app\api\controller\v1;
use app\api\validate\IDMustBePostiveInt;
use app\api\model\Banner as BannerModel;
use app\lib\exception\BannerMissException;
use think\Exception;
class Banner
{
public function getBanner($id){
(new IDMustBePostiveInt()) -> goCheck();
$banner = BannerModel::getBannerById($id);
if(!$banner){
//拋出異常 方式一
//throw new Exception;
//拋出異常 方式二 自定義異常
throw new BannerMissException();
}
return $banner;
}
}
//mode層 getBannerById
<?php
namespace app\api\model;
class Banner
{
public static function getBannerById($id)
{
return null;
}
}
//輪播圖沒找到異常 BannerMissException
<?php
namespace app\lib\exception;
class BannerMissException extends BaseException
{
public $code = 404;
public $msg = '請求Banner不存在';
public $errorCode = 40000;
}
//異常基類
<?php
namespace app\lib\exception;
use think\Exception;
class BaseException extends Exception
{
//HTTP 狀態碼 404,200
public $code = 400;
//錯誤具體信息
public $msg = '參數錯誤';
//自定義的錯誤碼
public $errorCode = 10000;
}
//程序種拋出的異常,會一層層向上拋出。若一直沒有處理,會到達最終的異常處理類handle類 \think\exception\Handle
//我們繼承 Handle類 並重寫了render方法
//修改config.php中 系統Handle的位置 這樣異常就會拋到我們自定義的Handle類
'exception_handle' => 'app\lib\exception\ExceptionHandler',
//自定義的handle類 修改config.php後啓用
//render方法 需要傳入\Exception 而不是Exception
//因爲有時會出現 Exception外的異常 這樣就會報錯 \Exception是基類兼容所有異常
<?php
namespace app\lib\exception;
use think\Exception;
use think\exception\Handle;
use think\Request;
class ExceptionHandler extends Handle
{
private $code;
private $msg;
private $errorCode;
//客戶要返回客戶端的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 = '服務器內部錯誤,不想告訴你!';
$this -> errorCode = 999;
}
$request = Request::instance();
$result = [
'msg' => $this -> msg,
'error_code' => $this -> errorCode,
'request_url' => $request -> url()
];
return json($result, $this -> code);
}
}