关于抛出异常我在上一篇文章中说过,在接口的设计中,接口返回的数据非常重要,比如不可避免的500等待,这些都是致命的错误,还有另一个大问题,这是在新模块中。比如我最近需要添加一个elasticsearch的分词查询模块。在添加索引、删除索引等操作时,很容易导致抛出错误异常。按照通常的解决方法,我们可能先用Exception直接捕获异常处理,/smile, 我以前也很喜欢这样做1)trycatch(1)代码示例:publicfunctionaddIndex($data){$params=['index'=>'show','type'=>'store','body'=>$data];试试{$this->client->index($params);}catch(\Exception$exception){halt('参数错误异常');#处理错误1}}在我们最初的研究和开发中,上面的方法确实是可行的,类似于我们常说的 JQ一梭 ,上面的 就是 的错误跨越了板子,这个方法确实可以解决问题, 但是效果很差处理一个错误比如 是有好处的BadRequest400Exception方法抛出的getMessage()结果是json数据,BadMethodCallException抛出的是字符串数据。你能告诉我如何处理吗?因此推导出第二种错误处理方法如下2)trycatch(2)代码案例:publicfunctionaddIndex($data){$params=['index'=>'show','type'=>'store','正文'=>$数据];试试{$this->client->index($params);}catch(BadRequest400Exception$e){$msg=json_decode($e->getMessage(),true);halt('参数错误异常:'.$msg);#处理错误1}catch(BadMethodCallException$e){halt('方法不存在错误异常:'.$e->getMessage());# 错误处理2}catch(\Exception$e){halt('系统异常');}}嗯,确实,上面也是一种常见的解决方案,但是你有没有考虑过代码冗余?10个需要捕获错误的方法,是不是只写10个?这时候,我们就需要一个操作来耦合这些方法。虽然php7对错误和异常的支持越来越强,但是面对不断增加的业务场景,我们必须采用可靠和稳定理解的三个标准来要求它。理解就是可以输出清晰的错误日志,方便我们进入正题。开发框架是thinkphp5.1异常处理接手thinkphp为我们提供了强大的异常处理机制,当然市面上的框架基本都能提供这个功能。我们找到了文档错误处理的部分,(https://www.kancloud.cn/manua...[https://www.kancloud.cn/manual/thinkphp5_1/354092#_42]基于tp自己的,然后在它的基础上优化了更丰富的自定义异常处理,这就是我理解的异常处理接管。我们来进行业务设计,定义一个异常处理接管,重写render方法,这个方法主要是抛出响应异常。注意~~!!查看源码和我的经验,一定是return方法,返回Response创建的响应异常,否则会抛出莫名其妙的错误阅读下面的文章,请查看http://surest.cn/archives/71/这篇文章主要是了解https://github.com/surest-sky/example/blob/master/laravel%E7%9A%84%E4%B8%80%E4%BA%9B的用法%E5%86%99%E6%B3%95/ApiResponse_tp.php异常处理接管代码如下isAjax()||$isDebug){//returnparent::render($e);//}#错误信息,用于写入日志$error_info=['code'=>$e->getCode(),#错误码描述'line'=>$e->getLine(),#错误行'message'=>$e->getMessage(),#错误详细信息'file'=>$e->getFile()#错误文件名];#捕获错误处理异常return$this->handler_exception($e,$error_info);}赶上(\异常$异常){返回父级::渲染($异常);}}/***加载错误处理*@param$e*/publicfunctionhandler_exception($e,$error_info){foreach($this->handler_exceptionsas$exception){$exception=new$exception;if($exception->handler($e,$error_info)instanceofResponse){返回$exception->handler($e,$error_info);它的流程大概是handler_exceptions:定义需要捕获异常的错误处理模块render:重写错误处理异常error_info用于将异常分发到各个子模块,在需要的地方打印日志catch(\Exception$exception):这个用处不大,主要是有错误,如果自己处理不了,可以交给tp内置的异常处理来处理returnparent::render($exception);执行父方法handler_exception,就是遍历需要捕获错误的模块,依次Load,当真正响应错误时(会继承Response方法),说明确实发生了错误,详见以下功能模块的异常处理见PhpStorm创建的elasticSearchshowMsg($e->getMessage(),$error_info);}休息;案例'Elasticsearch\Common\Exceptions\BadRequest400Exception':return$this->showMsg(json_decode($e->getMessage(),true),$error_info);休息;}#否则不返回错误异常}}过程解释,上面可以看到,我们继承了BaseException,实现了CustomExceptionInterface接口BaseExceptionnamespaceappcommonexception;useappcommonTraitsApiResponse;classBaseException{useApiResponse;publicfunction__construct(){#这个必须强制设置为真$this->is_anomaly_andling_takeover=true;#检查当前异常处理是否继承了异常处理接管,如果没有则抛出异常if(!($thisinstanceofCustomExceptionInterface)){return$this->showMsg(__CLASS__.'required必须继承接口CustomExceptionInterface',[]);}}publicfunctionshowMsg($msg,array$error_info,$code=500){返回$this->status($msg,compact('error_info'),$code,$code);}}CustomExceptionInterfaceis_anomaly_andling_takeover这是重写response定义ApiResponse,publicfunctionrespond($data,$header=[]){$type=request()->isAjax()在原来的ApiResponse?'json':“html”;$response=JsonResponse::create($data,$type,$this->code,$header);抛出新的HttpResponseException($response);}他就是直接抛出的HttpResponseException错误显然不符合我们之前说的必须返回的方式,返回一个Response创建的响应异常,否则会抛给你一个莫名其妙的错误,所以重新定义属性publicfunctionrespond($data,$header=[]){$type=request()->isAjax()?'json':“html”;$response=JsonResponse::create($data,$type,$this->code,$header);如果($this->is_anomaly_andling_takeover){返回$response;#throwresponse exception}thrownewHttpResponseException($response);}这样 showMsg方法返回response 在子类处理程序方法中,您可以轻松定义错误异常publicfunctionhandler($e,array$error_info){$e_class=get_class($e);switch($e_class){case'Elasticsearch\Common\Exceptions\UnexpectedValueException':return$this->showMsg($e->getMessage(),$error_info);}休息;案例'Elasticsearch\Common\Exceptions\BadRequest400Exception':return$this->showMsg(json_decode($e->getMessage(),true),$error_info);休息;}#否则不会返回错误异常}如前所述,我们可以将添加代码的字符串演化为publicfunctionaddIndex($data){$params=['index'=>'show','type'=>'存储','正文'=>$数据];$this->client->index($params);}不需要再捕获了,如果抛出错误,它会自动转到处理程序,并响应您定义的异常,然后添加错误处理。众所周知,路由出现异常问题是在所难免的。我们这样定义吧,在app\common\的exception\Handler属性handler_exceptions中加入'\app\common\exception\RouteExceptionHandler',定义他...使用think\exception\HttpException;classRouteExceptionHandlerextendsBaseExceptionimplementsCustomExceptionInterface{publicfunctionhandler($e,array$err_info){#检测原因错误if($einstanceofHttpException){return$this->showMsg("当前请求路由做不存在",$err_info,404);}}响应结果:{"msg":"当前请求路由不存在","code":404,"error_info":{"code":0,"line":63,"message":"modulenotexists:store","file":"/www/wwwroot/app/thinkphp/library/think/route/dispatch/Module.php"}}完整的代码示例在https://github.com/surest-sky/example/tree/master/exceptionsource邓晨峰
