最近在扩展抓取pdo的时候发现了点问题,发现有的是报异常,有的是不报,
<?php error_reporting(E_ALL ^ E_DEPRECATED); try{ $opts = array(PDO::ATTR_AUTOCOMMIT=>0, PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION, PDO::ATTR_AUTOCOMMIT=>0,PDO::ATTR_TIMEOUT => 3,); $pdo = new PDO("mysql:host=127.0.0.1;port=3306;dbname=test;charset=UTF8","root","root",$opts); $rs = $pdo -> query("select * from bankaa"); } catch(exception $e){ print_r($e);exit; } 在我的底层扩展是能抓到EG(exception)的,但是同事用了个底层php框架类,就抓不到了,最后跟踪断点发现
跟踪到
发现了一个变量
此为默认模式。 PDO 将只简单地设置错误码,可使用 PDO::errorCode() 和 PDO::errorInfo()方法来检查语句和数据库对象。如果错误是由于对语句对象的调用而产生的,那么可以调用那个对象的 PDOStatement::errorCode() 或 PDOStatement::errorInfo() 方法。如果错误是由于调用数据库对象而产生的,那么可以在数据库对象上调用上述两个方法。
除设置错误码之外,PDO 还将发出一条传统的 E_WARNING 信息。如果只是想看看发生了什么问题且不中断应用程序的流程,那么此设置在调试/测试期间非常有用。
这个图就把一个throw抛出异常以及到抓到catch异常的整个流程分析的很清楚。
zend_throw_exception_internal就相当于手动的throw一个异常,如果是php代码的话一般会有见到这样一个ZEND_THROW_SPEC_CV_HANDLER
但最终调用的都是zend_throw_exception_internal
在这个函数过后,会跳到一个ZEND_HANDLE_EXCEPTION_SPEC_HANDLER也就是我们经常发现的会跳到每一个op array的最后一行, 来执行这条ZEND_HANDLE_EXCEPTION,在这个函数中会判断如果是异常则把下一条要执行的op line, 置为第一个catch的op line, 并继续执行.如果不是 则销毁一些不需要的变量, 和opline, 然后直接结束执行过程.
如果有被catch到就会执行ZEND_CATCH_SPEC_CONST_CV_HANDLER,从而把EG(exception)=NULL
如果没有被catch,层层向上抛,最后就会发现最后调用zend_leave_helper_SPEC,离开函数。
在退出真正的执行之前,还有一层判断,就是有没有自定义的异常处理,如果有继续执行,没有直接退出运行。
