🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 异常和错误处理 如果每一次去逐一检查错误,会让代码变得冗长复杂,到处充斥着`if...else` ,并且严重降低代码的可读性.而且人的因素也是不可信赖的,程序员可能并不会把这问题当一回事,从而导致业务异常. **在这种情况下,就逐渐形成了异常处理机制,或者强迫消除这些问题,或者把问题交给能解决他的环境.** **这就把在正常过程中"做什么事的代码"和"出了问题怎么办的代码"进行分离** # 和java区别 在各种语言里,异常和错误的概念是不一样的.php里,遇到任何自身错误都会触发一个错误,而不是抛出异常(对于一些情况,会同时抛出异常和错误.php一旦遇到非正常代码,通常都会触发错误,而不是抛出异常.这时候想要异常处理是不可预料的,是办不到的) ~~~ try{ 5/0; }catch(Exception $e) { echo '异常处理'; } ~~~ 对于除零这种"异常"情况,php认为是一个错误,直接触发错误(waring也是错误,只是等级不同),而不会自动抛出异常进入异常流程,故最终没有走到异常分支,也没有处理异常. php只有你主动throw后,才能捕获异常(也有些异常,php可以自动捕获) php无法自动捕获有意义的异常,它把所有不正常的情况都视作错误,你要捕获这个异常,就得使用if..else结构.保证代码是正常的.但php这个机制并不完善,php内置有一些pdo异常,反射异常 ~~~ try { if ((5/0) || 1) { echo '异常发生了',PHP_EOL; } }catch(Exception $e) { //最终无法catch,因为是错误 echo '异常catch住了'; } ~~~ **注意** **其实php和java之间之所以有这样的差距,根本在于,在java里,异常是唯一的错误报告方式.而在php里却不是这样. 通俗一点讲,就是这2个语言对异常和错误的界定存在分歧. 什么是异常,什么是错误,2个语言的设计存在不同的观点** **php只有手动抛异常和内置异常机制,才能捕获异常,否则是先触发错误,再异常** ![](https://box.kancloud.cn/4ad0e7c658c3191d771f59dd9780a2c1_650x160.png) # 异常 ## 自己定义异常 ~~~ <?php class emailException extends exception { } class pwdException extends exception { function __toString() { //改写抛出异常结果 return "<div class=\"error\"> Exception{$this->getCode()}:{$this->getMessage()} in File:{$this->getFile()}on line:{$this->getLine()}</div>"; } } function reg($reginfo=null) { if(empty($reginfo['email'])) { throw new emailException('邮件为空',500); } if(empty($reginfo['pwd'])) { throw new pwdException('密码没填写',501); } echo '注册成功'; } ~~~ 处理异常 ~~~ try { reg(); }catch(emailException $e) { echo $e->getMessage(),$e->getCode(); echo PHP_EOL; }catch(pwdException $e) { echo $e; echo PHP_EOL,'特殊处理'; }catch(Exception $e) { echo $e->getTraceAsString(); echo PHP_EOL,'其他情况,统一处理'; } ~~~ 这段代码用于捕获各种抛出的异常,进行分类处理,记住大的exception在最后catch住 ## 异常应用场景 **对程序悲观预测** 并不是指程序员的代码水平不行,而是有些代码发生场景无法一一预测,并且有些业务是非常重要的 **对业务关注** 那么就可以在catch的捕获中进行业务补偿处理 合理代码应该是这样 ![](https://box.kancloud.cn/0c30068d100a701c20d8deafa6f710fe_442x197.png) **异常处理机制可以把每一件事情当做事务考虑,还可以把异常看作一个内建的恢复系统. 如果程序某部分失败,异常将恢复到某个已知稳定的点上,而这个点就是程序的上下文环境,而try块里面的代码就保存catch所要知道的程序上下文环境. 因此,如果很看重异常,就应该分散进行try...catch..处理** ## 语言健壮级别 ![](https://box.kancloud.cn/11ea85b4b6f5172452caec3bf1ef22c9_755x209.png) ## 怎么看php中的异常 ![](https://box.kancloud.cn/adb2208d174458b7eca426ab2384bb9a_662x471.png) # 错误 php错误处理比异常价值大多了 php错误就是会使脚本运行不正常的情况 请确保php.ini做了如下设定 ~~~ error_reporting = E_ALL | E_STRICT display_errors = On ~~~ 如果你想隐藏错误可以这样 ~~~ error_reporting(0); 或者代码前面加@ ~~~ ## 错误处理机制 php有一套全局错误处理机制set_error_handler,你也可以用trigger_error函数主动抛出一个错误 set_error_handler用户自定义错误处理会接管php内置的错误处理,你可以在一个页面使用restore_error_handler来取消接管 注意如果用set_error_handler,代码中的@也会失效,这种错误会显示 php异常机制是有限的,无法自动抛出异常,必须手动进行,并且内置异常是有限的. php把很多异常看作是错误,这样可以把这些异常像错误一样用set_error_handler接管,进而进行主动抛出异常 ![](https://box.kancloud.cn/169c37a8e705e029e13fb9a97e14706d_453x294.png) **但是fetal error这种错误是捕获不到的,也无法在发生这个错误的时候进行恢复流程处理,但是还有一些特殊方法对这种错误进行处理的. 这时候需要一个函数-- register_shutdown_function,这个函数会在php程序终止或者die的时候触发一个函数,给代码来个回光返照** php4时候,类不支持析构函数,常用这个函数模拟实现析构函数 --- 对于fetal error还能做点收尾工作,但是php流程的终止必然的,对于Parse error级别错误,只能傻眼了,除了可以修改ini文件,什么也做不了 ~~~ log_errors = On error_log = usr/log/php.log ~~~ 这样一旦发生错误会被记录log文件,方便以后查询 和exception类似,错误处理也有对应抛出函数,那就是trigger_error函数,如下 ![](https://box.kancloud.cn/1e3824d7e18275dd818c81983d1c38d9_399x112.png)