在 PHP 7 中,很多致命错误以及可恢复的致命错误,都被转换为异常来处理了。不同于传统(PHP 5)的错误报告机制, 这些异常继承自 Error 类,此类实现了 ​​Throwable​​ 接口 (所有异常都实现了这个基础接口)。

这也意味着,当发生错误的时候,以前代码中的一些错误处理的代码将无法被触发。 因为在 PHP 7 版本中,已经使用抛出异常的错误处理机制了。 (如果代码中没有捕获 Error 异常,那么会引发致命错误)。

Error 类并非继承自 Exception 类,所以不能用 catch (Exception $e) { … } 来捕获 Error。这种 Error 异常可以像 Exception 异常一样被第一个匹配的 try / catch 块所捕获。如果没有匹配的 catch 块,则调用异常处理函数(事先通过 ​​set_exception_handler()​​注册)进行处理。 如果尚未注册异常处理函数,则按照传统方式处理:被报告为一个致命错误(Fatal Error)。

​set_exception_handler()​​​ 不再保证收到的一定是 Exception 对象
抛出 Error 对象时,如果 ​​​set_exception_handler()​​里的异常处理代码声明了类型 Exception ,将会导致 fatal error。

想要异常处理器同时支持 PHP5 和 PHP7,应该删掉异常处理器里的类型声明。如果代码仅仅是升级到 PHP7,则可以把类型 Exception 替换成 Throwable。

// PHP 5 时代的代码将会出现问题
function handler(Exception $e) { ... }
set_exception_handler('handler');

// 兼容 PHP 5 和 7
function handler($e) { ... }

// 仅支持 PHP 7
function handler(Throwable $e) { ... }
?>

Error 层次结构

Throwable
– Error
---- ArithmeticError
-------- DivisionByZeroError
---- AssertionError
---- ParseError
---- TypeError
---- Exception

You can catch both exceptions and errors by catching(​​Throwable​​​)
Throwable does not work on PHP 5.x.

To catch both exceptions and errors in PHP 5.x and 7, add a catch block for Exception AFTER catching Throwable first.
Once PHP 5.x support is no longer needed, the block catching Exception can be removed.

try
{
// Code that may throw an Exception or Error.
}
catch (Throwable $t)
{
// Executed only in PHP 7, will not match in PHP 5
}
catch (Exception $e)
{
// Executed only in PHP 5, will not be reached in PHP 7
}
  • 当内部构造器失败的时候,总是抛出异常
    在之前版本中,如果内部类的构造器出错,会返回 NULL 或者一个不可用的对象。 从 PHP 7 开始,如果内部类构造器发生错误, 那么会抛出异常。
  • 解析错误会抛出 ParseError 异常
    解析错误会抛出 ParseError 异常。 对于 eval() 函数,需要将其包含到一个 catch 代码块中来处理解析错误。
  • E_STRICT 警告级别变更
    原有的 E_STRICT 警告都被迁移到其他级别。 E_STRICT 常量会被保留,所以调用 ​​error_reporting(E_ALL|E_STRICT)​​不会引发错误。