# 前言
*****
在使用thinkphp框架开发中,遇到很多需要捕获异常的情况
* 如往数据库插入数据时如果异常则抛出:数据插入失败,
* 请求第三方接口异常时候抛出:接口异常,原因:XXXX
* 其他更多场景
```php
<?php
//我们捕获异常的代码可能是这样的
try {
$user = new User;
$user->name = 'thinkphp';
$user->email = 'thinkphp@qq.com';
$user->save();
} catch (\Exception $e) {
return json(['code' => -1, msg => '用户添加失败:' . $e->getMessage()]);
}
}
```
那除了不停的try catch之外,是否有更加便捷高效的方法来统一捕获这些异常,并且能够在第一时间自动利用微信消息通知我们呢?答案是肯定的.本文将与大家分享thinkphp5.1的异常处理接管以及使用微信企业号实时通知程序异常告警,以便开发者在第一时间排查问题并做出对应处理.
# Thinkphp5.X 之异常自定义接管
*****
thinkphp框架为我们提供了一个非常便利的功能就是异常自定义接管,首先我们为什么要自己去接管异常,有何使用场景?
* 例如在开发API接口时希望只要程序有异常时对前端统一抛出: {code:-1,msg:"具体错误信息"}, 方便前端给用户弹出对应提示语 .
* 即上文提到的希望在程序有异常时通知开发者,以便主动做出对应处理,不必等待用户主动反馈报错再去排查.
首先建议读者先仔细阅读 [ThinkPHP5.1完全开发手册之异常处理章节]( https://www.kancloud.cn/manual/thinkphp5_1/354092), 我们先在应用配置文件app.php中配置参数 exception_handle ![](https://box.kancloud.cn/00d82cdbf7a692ccd2aa468a6df089dd_1566x389.jpg)
app\common\controller\Handle 异常接管类的文件可能如下
```php
<?php
namespace app\common\controller;
use Exception;
use think\exception\Handle as TpHandle;
use think\exception\HttpException;
use think\exception\ValidateException;
use think\console\Output as ConsoleOutput;
class Handle extends TpHandle
{
protected function alarm(Exception $exception)
{
try {
//将异常所在文件,以及行数 通知开发者 方便排查异常原因
$errmsg = $exception->getMessage();
$data = [
'title' => '程序异常通知',
'keyword1' => "file: " . $exception->getFile() . ';line:' . $exception->getLine(),
'keyword2' => "message: " . $errmsg,
];
//发送微信企业消息 通知开发者 下文会详细讲解
send_workweixin_textcard($data);
} catch (Exception $e) {
//需手动捕获异常,防止上文异常后死循环
trace('消息发送失败:'. $e->getMessage() . $errmsg, 'error');
}
}
public function report(Exception $e)
{
//异常通知
$this->alarm($e);
//交由Thinkphp框架继续处理
parent::report($e);
}
//在CLI命令行模式有异常时将由此方法接管
/**
* @param Output $output
* @param Exception $e
*/
public function renderForConsole(ConsoleOutput $output, Exception $e)
{
//异常通知
$this->alarm($e);
//交由Thinkphp框架继续处理
parent::renderForConsole($output, $e);
}
//在普通模式有异常时将由此方法接管
/**
* @param Exception $e
*/
public function render(Exception $e)
{
try {
$errmsg = $e->getMessage();
$data = [
'title' => '程序异常通知',
'keyword1' => "url: " . $url,
'keyword2' => "message: " . $errmsg,
];
//发送微信企业消息 通知开发者 下文会详细讲解
send_workweixin_textcard($data);
$data = [
'code' => intval($e->getCode()) ?: -1,
'msg' => $e->getMessage(),
];
//因本项目是API接口开发 统一返回固定格式
return json($data);
} catch (Exception $e) {
//需手动捕获异常,防止上文异常后造成死循环
trace('消息发送失败'. $e->getMessage(), 'error');
}
//交由Thinkphp框架继续处理
return parent::render($e);
}
}
```
> 让我们测试一下 当程序异常时会如何捕获异常,我们尝试测试如下代码:
```php
<?php
public function index()
{
//未定义变量 直接echo 将抛出异常
echo $b;
}
```
> 我们通过url访问此方法看如何提示
![](https://box.kancloud.cn/7a16a7bd0f5ecd4b749017834d889fa2_519x149.png)
至此,我们已经实现了统一捕获框架异常并按照统一格式抛出,极其适合API接口开发的项目, 这样永远抛出的都是一个合法的json且可被对方识别.方便将异常返回给前端.
# 利用微信企业号实时通知程序异常
*****
1. 首先我们需要申请微信企业号,[点击进入企业号官网]( https://work.weixin.qq.com),注册的流程将不再做过多讲解.
2. 创建应用以及获取企业ID[登录企业微信后台后点我查看](https://work.weixin.qq.com/wework_admin/frame#profile)和secret密钥 以获取access_token, 开发文档可参考 [点击进入开发文档]( https://work.weixin.qq.com/api/doc#10013/第三步:获取access_token)
3. 组转指定格式数据给对应开发者微信号推送消息
![](https://box.kancloud.cn/8f3ab4a5877f059116a123949854da2c_1423x1015.jpg)
![](https://box.kancloud.cn/d7691a80f646839a423a0976a500b024_1347x865.jpg)
![](https://box.kancloud.cn/2020cecd83d1b46cc08619344a315da6_1342x435.jpg)
因本人实际项目中使用的是封装的比较复杂方法,故附上伪代码,仅供参考 提供思路
```php
<?php
public function send_workweixin_textcard($data)
{
$corpid = '换成您wx开头的企业ID';
$agentid = '换成您的应用ID';
$access_token = $this->get_access_token();
$url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' . $access_token;
$description = "<div class=\"normal\">" . $data['keyword1'] . "</div><br>";
if (!empty($data['keyword2'])) {
$description .= "<div class=\"highlight\">" . $data['keyword2'] . "</div><br>";
}
$post_data = [
'corpid' => $corpid,
'data' => [
'touser' => 'xieyongfa',//成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送
'msgtype' => 'textcard',
'agentid' => $agentid,
'textcard' => [
'title' => $data['title'],
'description' => $description,
],
]
];
curl_post($url,json_encode($post_data)); //发送消息 curl post请求请自行百度实现
}
protected function get_access_token()
{
$corpid = '换成您wx开头的企业ID';
$corpsecret = '换成您的应用密钥';
$url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=' . $corpid . '&corpsecret=' . $corpsecret;
$json = curl_get($url); //curl 方法请自行百度
$result = json_decode($json, true);
if (isset($result['errcode']) || $result['errcode'] === 0) {
return $result['access_token']; //todo实际场景中请做好缓存逻辑
} else {
throw new \Exception('access_token获取异常' . $result['errmsg'], $result['errcode']);
}
}
```
效果图:这样我们即可快速定位到异常的文件以及行数
![](https://box.kancloud.cn/99d1a53ddb011f7626107fb23017fbec_1242x2208.png =250x440)
# 后记
## 开发帮助及交流
如您对本文感兴趣想与我联系交流 您可以
+ 邮件至:xieyongfa@ecarde.cn
+ QQ:2392523899 [点我聊天](http://wpa.qq.com/msgrd?v=3&uin=2392523899&site=qq&menu=yes&from=message&isappinstalled=0)
+ 微信交流
![](https://box.kancloud.cn/b74285a950ce81e3cb782f02eb118d59_752x974.jpg =300x389)