PHP中的异常和错误处理
在PHP5中所有错误异常都是基于Exception类,所有具体的异常类都是Exception的子类。而所有的errors都是致命错误或是可恢复性致命错误,是不能被捕获的(只会强制终止脚本)
在PHP7中,致命或是可恢复性错误(E_ERROR和E_RECOVERABLE_ERROR)可以捕获,而不是中止脚本(某些特定的情况下仍然会强制终止脚本,如内存不足)。为了防止PHP5的代码即使接收到的此类错误仍然会终止程序,致命或是可恢复性错误抛出并不延伸自Exception类,而是实例化一个新的异常类Error
Throwable类:为了联合这两个异常分支,Exception和Error都实现了一个新的接口Throwable,PHP7中新的异常层次如下:
Throwable |- Exception implements Throwable |- ... |- Error implements Throwable |- TypeError |- ParseError |- ArithmeticError |- DivisionByZeroError |- AssertionError
Exception类不再是最顶层的异常类,它和Error类同级别且都是Throwable类的子类,也就是说Throwable类是目前PHP中的最顶层异常类,所有的异常类都是它的子类。
捕获异常语句
try { 运行语句; }catch(Throwable $e){ print $e->getMessage(); }catch(Exception $e){ //兼容PHP5 print $e->getMessage(); }
Throwable类中的方法:
Throwable类中除__toString()外其他方法都是不可被重写的。
getMessage(); // 返回异常信息
getCode(); // 返回异常代码
getFile(); // 返回发生异常的文件名
getLine(); // 返回发生异常的代码行号
getTrace(); // backtrace() 数组
getTraceAsString(); // 已格成化成字符串的 getTrace() 信息
__toString(); // 可输出的字符串(可重载的方法)
Error类目前版本的子类:
TypeError 类型错误,当调用函数时的形参和实参类型不一致将会抛出一个TypeError
ParseError 编译错误,included/required引入文件,或者eval()中的代码包含语法错误时会抛出一个ParseError
ArithmeticError 算数错误,负数位移或调用intdiv(PHP_INI_MIN/-1)两种情况会抛出一个ArithmeticError
DivisionByZeroError 分母为零,分母为零时使用intdiv()或者取余(%)会抛出DivisionByZeroError(仅仅除零只会引起一个警告,计算结果为NaN)
AssertionError 断言错误,当不满足assert()设定的条件时,将会抛出一个AssertionError错误(需要php.ini中zend.assertions和assert.exception设置为1)
断言语句
assert(mixed $assertion[,string $description])
$assertion可以是一个字符串,会把该字符串作为php代码执行并返回执行的值(危险行为)
$description在PHP5中只可以是一个字符串,如果assertion返回false,将会包括在失败信息里。在PHP7中还可以是一个异常类的名称用于改变该断言语句抛出的异常类型。
assert_options ( int $what [, mixed $value ] )设置/获取断言的各种控制选项,分别对应php.ini中的配置项。
ASSERT_ACTIVE对应php.ini中的assert.active,默认值为1,表示启用assert()断言
ASSERT_WARNING对应php.ini中的assert.warning,默认值为1,表示为每个失败的断言产生一个 PHP 警告(warning)
ASSERT_BAIL对应php.ini中的assert.bail,默认值为0,表示在断言失败时中止执行
ASSERT_QUIET_EVAL对应php.ini中的assert.quiet_eval,默认值为0,表示在断言表达式求值时禁用error_reporting
ASSERT_CALLBACK对应php.ini中的assert.callback,默认值为NULL,表示断言失败时调用回调函数
常用的异常相关函数
set_exception_handler(callable $exception_handler)
设置自定义的默认异常处理函数,用于没有用try/catch块来捕获的异常。$exception_handler为一个未捕获的异常发生时所调用函数的名称。 该处理函数需要接受一个抛出的异常对象的参数,这个参数传入NULL则重置此次异常处理程序到系统默认状态
restore_exception_handler():把异常处理函数恢复为上一次使用set_exception_handler()方法之前的函数
set_error_handler(callable $exception_handler[,int $level = E_ALL | E_STRICT]):设置自定义的默认错误处理函数
restore_error_handler():把错误处理函数恢复为上一次使用set_error_handler()方法之前的函数
**error_reporting ([int $level])** 设置在脚本运行时的错误报告的级别$level可以是数值或对应的常量,返回旧的error_reporting级别,在$level参数省略时返回当前的级别
异常或错误级别的预定义常量:
值 | 常量 | 说明 |
1 | E_ERROR | 致命的运行时错误这类错误一般是不可恢复的情况,例如内存分配导致的问题后果是导致脚本终止不再继续运行 |
2 | E_WARNING | 运行时警告 (非致命错误)仅给出提示信息,但是脚本不会终止运行 |
4 | E_PARSE | 编译时语法解析错误解析错误仅仅由分析器产生 |
8 | E_NOTICE | 运行时通知表示脚本遇到可能会表现为错误的情况,但是在可以正常运行的脚本里面也可能会有类似的通知 |
16 | E_CORE_ERROR | 在PHP初始化启动过程中发生的致命错误该错误类似 E_ERROR,但是是由PHP引擎核心产生的 |
32 | E_CORE_WARNING | PHP初始化启动过程中发生的警告 (非致命错误) 类似 E_WARNING,但是是由PHP引擎核心产生的 |
64 | E_COMPILE_ERROR | 致命编译时错误类似E_ERROR, 但是是由Zend脚本引擎产生的 |
128 | E_COMPILE_WARNING | 编译时警告 (非致命错误)类似 E_WARNING,但是是由Zend脚本引擎产生的 |
256 | E_USER_ERROR | 用户产生的错误信息类似 E_ERROR, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的 |
512 | E_USER_WARNING | 用户产生的警告信息类似 E_WARNING, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的 |
1024 | E_USER_NOTICE | 用户产生的通知信息类似 E_NOTICE, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的 |
2048 | E_STRICT | 启用 PHP 对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性 |
4096 | E_RECOVERABLE_ERROR | 可被捕捉的致命错误 它表示发生了一个可能非常危险的错误,但是还没有导致PHP引擎处于不稳定的状态 如果该错误没有被用户自定义句柄捕获 (参见 set_error_handler()),将成为一个 E_ERROR 从而脚本会终止运行 |
8192 | E_DEPRECATED | 运行时通知启用后将会对在未来版本中可能无法正常工作的代码给出警告 |
16384 | E_USER_DEPRECATED | 用户产少的警告信息 类似 E_DEPRECATED, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的 |
30719 | E_ALL | E_STRICT除外的所有错误和警告信息 |
上面的值(数值或者常量)用于建立一个二进制位掩码,可以使用按位运算符来组合这些值或者屏蔽某些类型的错误。请注意,在 php.ini 之中,只有'|', '~', '!', '^' 和 '&' 会正确解析。