tp5任何地方抛出异常,最终返回json

浏览:3058 发布日期:2018/06/26 分类:功能实现 关键字: 异常 json
在前后分离开发中,如vue,后台只能返回json格式。在参数验证中希望抛出异常,并由repsonse统一处理,返回json。而默认的异常处理都是返回页面,因而需要调整

最近在用vue与yii开发,需要返回json格式,并且在参数验证失败的情况下,采用抛出异常的方式,然后用Respone统一处理异常,有感于此,突发奇想,如果用tp该怎么办呢。于是进行摸索。想啊想,都找不到一种方法能够在不用try catch的情况下捕获异常,毕竟总不能每个方法里都写上try catch,直到发现手册上写着'exception_handle' => '\\app\\common\\exception\\Http',接管框架异常处理类,于是故事就此开始。

分析过程如下:
1. 在\think\base.php中有如下一行代码\think\Error::register(),此为注册异常处理代码,在这个register中有代码set_exception_handler([__CLASS__, 'appException']);,说明框架是采用\think\Error::appException方法处理异常。
2. 在appException中有如下代码
if (IS_CLI) {
//这是命令行下执行
self::getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
} else {
self::getExceptionHandler()->render($e)->send();
}
在这个getExceptionHandler中$class = Config::get('exception_handle');,$handle = new $class;
也就是说从配置项exception_handle创建了一个异常处理handler对象。

于是self::getExceptionHandler()->render($e)就表示调用了handler对象的render方法,并且传入了异常对象$e作为参数,这个函数最终返回一个response对象。因此可以在自定义异常处理类中重写render方法。

3. 重写render方法
public function render(\Exception $e){
$response = new Response($e, 200);
return $response;
}
这里把异常对象作为data给response对象,框架render也是实例化一个response,然后返回的,只是想说都是参考。

4. 在框架\think\Response的send方法中,监听了一个标签位response_send,而这个标签位居然没有在手册中提起。现在实现这个标签功能,目的是处理异常或者控制器返回的数据。
public function run($response)
{
//获取response原始数据
$data=$response->getData();

$responseData=[];
//如果原始数据是异常
if ($data instanceof \Exception){
$responseData=['errcode'=>$data->getCode(),'errmsg'=>$data->getMessage()];
}else{
//如果原始数据返回的是false,比如控制器直接返回了false
if (false === $data){
$responseData=['errcode'=>-1,'errmsg'=>'未知错误'];
}else{
//如果原始数据返回的是true或者其它数据
$responseData=true === $data ? ['errcode'=>0,'errmsg'=>'成功']
: ['errcode'=>0,'errmsg'=>'成功','items'=>$data];
}
}
//重新设置response对象的数据
$response->data(json_encode($responseData,JSON_UNESCAPED_UNICODE));
}

总结:
1. 需要实现自定义的异常处理类,接管框架的,并实现render方法,把当前异常作为data传给response对象。其实这一步也是为了下一步。配置'exception_handle' =>自己的异常类。

2. 为了简化控制器返回数据,比如成功就返回true,失败false,或者数据,但是考虑到实际需要返回的是json,因而利用了系统预置的response_send标签位,根据控制器返回值改变实际返回值,比如控制器返回false的时候,实际返回json_encode(['errcode'=>-1,'errmsg'=>'未知错误'])。也正是基于此,所以才把异常传给response,因为始终都要用到这个标签位。

第一次写,很慌(来自一个一年工作经验的小白)。
评论( 相关
后面还有条评论,点击查看>>