AOP 编程思想,即面向切面编程思想,通俗的说,就是用统一的方式处理问题,而不是用相同的方式分别处理多个问题,对于异常处理来说,就是定义统一的异常信息,用统一的方式处理
大致思路
自定义异常处理类,重写默认异常处理类的 render 方法,然后配置使用自定义异常处理类处理所有异常
代码实现
在根目录下创建目录 exception,在其下创建ExceptionHandle.php,此类要继承 handle 类
class BaseException extends Handle
class BaseException extends Exception
{
//创建几个属性,用于定义异常信息
public $code = 400 ;
public $msg = '参数错误';
public $errorcode = 1000 ;
}
覆盖 Handle 类中的render 方法,当我们在代码中使用 throw new Exception() 方式抛出异常信息时,其实就是调用了 render 方法,所以我们要重写此方法,以返回我们自己的信息
<?php
namespace app\common\exception;
use app\services\robot\RobotService;
use think\exception\Handle;
class Http extends Handle
{
private $code ;
private $msg ;
private $errorcode;
public function render(\Exception $e)
{
if($e instanceof BaseException){
$this->code = $e->code ;
$this->msg = $e->getMessage() ;
$this->errorcode = $e->errorcode ;
}else{
$this->code = 500 ;
$this->msg = '系统繁忙,请稍后重试';
$this->errorcode = 999 ;
$send_msg = array(
'message' => $e->getMessage() ,
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTrace(),
);
RobotService::send_error_msg($send_msg);
}
return json_error($this->msg,$this->errorcode, $this->code);
}
}
使用自定义的异常处理
在 config.php 中修改如下配置
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => 'app\lib\exception\ExceptionHandler',
自定义异常处理类
一类异常是用户行为导致的异常,比如没有查询到符合条件的数据(从另一个角度来说,这其实不算异常),一类错误是运行时错误。而用户导致的异常可能分为很多种,所以需要自定义相关的类。
首先定义一个父类
class BaseException extends Exception
{
//http 状态码
public $code;
//错误具体消息
public $msg;
//自定义错误码
public $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'];
}
}
}
再定义一个处理找不到产品信息的异常处理类,用来重写父类中的各个属性,而且这个类中的属性信息也可能会被修改,如 msg
class ProductNotFoundException extends BaseException
{
//http 状态码
public $code = 404;
//错误具体消息
public $msg = "请求的产品不存在";
//自定义错误码
public $errorCode = 40000;
}
处理不同异常
在 render 方法中,根据异常的不同分别处理
//分别处理两种不容类型异常:1、用户错误 2.代码与运行时错误
if ($ex instanceof BaseException) {
} else {
}
说明:在 throw 异常时,会执行 render 函数,同时会将抛出的异常对象复制给参数 $ex,所以可以根据此参数判断异常类型
现在的关键是生产环境,所以希望返回的异常信息,前端人员能够看懂,而不是像上面那样在页面中输出错误信息,还包括堆栈信息等。
那么前端后端人员都能够看懂的信息一定是 json(当然也可以是xml)了,修改 render 方法
if ($ex instanceof BaseException) {
$this->code = $ex->code;
$this->msg = $ex->msg;
$this->errorCode = $ex->errorCode;
} else {
//这里是在运行时产生的各种异常,所以无法准确输出异常信息,所以只能统一输出是服务器错误信息
$this->code = 500;
$this->msg = "服务器内部错误";
$this->errorCode = 999;
}
$result = [
'msg' => $this->msg,
'error_code' => $this->errorCode,
'request_url' => request()->url()
];
return json($result,$this->code);
全局的异常处理就编写好了,下面在 product.php 中编码进行测试
public function getProduct($id)
{
//处理程序运行时错误
/*try{
3/0;
}
catch(Exception $ex){
throw $ex;
}*/
//处理用户行为产生的错误
$error=[
'msg'=>'没有找到合适的产品'
];
$ex=new ProductNotFoundException($error);
throw $ex;
}