一、固有思维模式
目录结构
//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);
}
}