💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、豆包、星火、月之暗面及文生图、文生视频 广告
tp5.1可以自定义异常接管,具体参见文档[异常处理接管](https://ihavenolimitations.xyz/manual/thinkphp5_1/354092#_42) 但是在实际的项目开发过程中,我们可能会面对这样的需求: 1、后端需要记录各类异常信息 2、前端只抛出固定的错误信息 3、不同的异常级别对应处理方案不同 本文就简单介绍异常处理接管的各种骚操作: ## 1、自定义异常接管类 我们首先新建一个`app\common\exception\CommonHandler`类,并在项目配置文件中,修改`exception_handle`配置。 ``` use think\exception\Handle; use think\exception\ValidateException; class CommonHandler extends Handle { public function render(\Exception $e) { // 参数验证错误 if ($e instanceof ValidateException) { return json($e->getMessage()); } // 其他错误交给系统处理 return parent::render($e); } } ``` 这段代码表示,当`think\exception\ValidateException`抛出异常时,返回json格式的错误信息。但是在实际开发过程中,我们光有异常信息抛出可能远远不够,那我们来扩展一下这个功能。 ## 2、自定义一个异常类 我们再建一个`app\common\exception\AppValidateException`类,用于项目内验证类的手动抛出。 ``` use think\Exception; class AppValidateException extends Exception { public $msg; public $status; public $data; public $url; public function __construct($msg,$status=1,$data=[],$url='') { $this->msg = $msg; $this->status = $status; $this->data = $data; $this->url = $url; } } ``` 再将`app\common\exception\CommonHandler`修改一下: ``` use think\exception\Handle; use think\exception\ValidateException; class CommonHandler extends Handle { public function render(\Exception $e) { //自定义的异常类,注意先后顺序 if($e instanceof AppValidateException){ $data['status'] = $e->status; $data['msg'] = $e->msg; $data['data'] = $e->data; $data['url'] = $e->url; return json($data); } // 参数验证错误 if ($e instanceof ValidateException) { return json($e->getMessage()); } // 其他错误交给系统处理 return parent::render($e); } } ``` 这样,我们在后端使用`throw new AppValidateException('手机号码格式错误');`即可直接返回json格式的数据。 ## 3、日志记录与服务监控 这个时候,老板/产品经理/其他杂七杂八人员又说,光有报错不行,我们要记录程序错误和必要的客户信息。好的,那就给你实现。 `app\common\exception\AppValidateException`自定义异常类: ``` namespace app\common\exception; use think\Exception; class AppValidateException extends Exception { public $msg; public $status; public $data; public $url; public $level; public function __construct($msg,$level=1,$status=1,$data=[],$url='') { $this->msg = $msg; //语义提示内容 $this->status = $status; //状态码 $this->data = $data; //返回的数组 $this->url = $url; //url,可提供给前端跳转 $this->level = $level; //异常级别,用于日志记录和判断错误记录等 } } ``` `app\common\exception\CommonHandler`自定义异常接管类: ``` namespace app\common\exception; use think\exception\Handle; use think\exception\ValidateException; use think\facade\Log; class CommonHandler extends Handle { protected $error; public function render(\Exception $e) { //自定义的异常类,注意先后顺序 if($e instanceof AppValidateException){ $this->getException($e); $this->analyze($e->level,$e->status,$e->data,$e->url); $data['status'] = $e->status; $data['msg'] = $e->msg; $data['data'] = $e->data; $data['url'] = $e->url; return json($data); } // 参数验证错误 if ($e instanceof ValidateException) { return json($e->getMessage()); } // 其他错误交给系统处理 return parent::render($e); } protected function analyze($level,$status,$data,$url) { $log['status'] = $status; $log['data'] = $data; $log['url'] = $url; $log['error'] = $this->error; //异常级别 switch (true){ case $level==2: $log['level']='app_warning'; //self::sendEmail($log) 发送邮件 break; case $level==3: $log['level']='app_error'; //self::sendSMS() 发送短信 break; default: $log['level']='app_notice'; } Log::record($log,$log['level']); return true; } protected function getException($e) { if($e instanceof \Exception) { $this->error = [ 'name' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'msg' => $e->msg, ]; } return $this; } } ``` 当我们手动抛出异常: ``` throw new AppValidateException('这是一个error级别异常',3); ``` 我们会在日志文件中找到以下日志记录: ``` [ 2018-11-30T16:26:44+08:00 ] 127.0.0.1 GET www.xxx.com/index.php/index/index/hello [ error ] [0] [ app_error ] array ( 'status' => 1, 'data' => array ( ), 'url' => '', 'error' => array ( 'name' => 'app\\common\\exception\\AppValidateException', 'file' => 'D:\\wamp\\www\\www.xxx.com\\php\\application\\index\\controller\\Index.php', 'line' => 15, 'msg' => '这是一个error级别异常', ), 'level' => 'app_error', ) ``` ok,异常接管的骚操作就到这了。