上手并过渡到PHP7(4)——取代fatal error的engine exceptions

发布时间:2019-08-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了上手并过渡到PHP7(4)——取代fatal error的engine exceptions脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

上手并过渡到PHP7

取代fatal error的engine exceptions

泊学原文链接
泊学代码秀视频

自从PHP 4以来,PHP的错误处理几乎就是一成不变的。只不过在PHP 5.0里添加了E_STRICT,在PHP 5.2里添加了E_RECOVERABLE_ERROR,在PHP 5.3里,添加了E_DPRECATED这几种Error level。尽管PHP 5中加入了Exception,但PHP中只有很少的模块使用了这个机制(例如:pdo和spl)。在PHP 7中,这个尴尬现状,终于被彻底改变了。

Engine Exceptions

PHP 7里,几乎所有的Fatal和catchable fatal error都被替换成了 Engine exceptions 。但是,所有未被catch的异常仍旧会导致一个“传统”的PHP fatal error,因此,对于各种fatal error来说,这个改动几乎是向前兼容的。但对于其他类型的Error(non-fatal)来说,由于它们也被转换成了异常,忽略它们同样会导致一个fatal error,因此,对这些错误的处理,并不向前兼容。

把各种错误统一成异常的一个好处,就是我们可以使用try...catch来统一处理它们,进而,为错误现场的正确清理提供诸多保障:

  • 确保finally内的代码被调用;

  • 确保类的__destruct()函数被调用;

  • 使用register_shutdown_function()注册的回调函数被调用;

总之,因为有了engine exceptions,错误更不容易被忽略,也更容易被处理。我们来看一个例子: 构造函数中发生异常会怎么样呢?

getMessage();
}

在PHP 5里,$msg会是一个null或不可用对象。在PHP 7里,MessageFormatter则会抛出一个IntlException异常:Constructor failed。

PHP 7 Exception架构

为了能够和PHP 5兼容,我们必须确保之前的call-all写法:

getMessage();
}

不能捕获新的PHP 7 engine exceptions(因为在PHP 7之前,Fatal error是不能够被捕获和处理的)。这样,那些没有被处理的异常,才会像之前一样导致一个Fatal error。因此,所有新的engine exception并没有继承之前的Exception类,而是继承了一个新的叫做Error的基类。

class Error implements Throwable {
    /* InherITed methods */
    abstract public string Throwable::getMessage ( void )
    abstract public int Throwable::getCode ( void )
    ...
}

基于Error exception,派生了5个新的engine exception:ArithmeticError / AssertionError / DivisionByZeroError / ParseError / TyPEError。在PHP 7里,无论是老的Exception还是新的Error,它们都实现了一个共同的interface: Throwable。因此,Throwable是PHP 7异常架构里最顶层的接口。所以,如果你想在PHP 7里实现一个catch-all,你可以这样:

getMessage();
}

Error exception

接下来,我们来分别了解一下新增的这几个engine exception:

Error

这个异常代表了PHP 7中标准的fatal和catchable-fatal错误,如果它不被catch,就会进而触发一个“传统”的PHP fatal error。例如,我们调用一个不存在的方法:

try {
    nonExistFunc();
}
catch(Error $e) {
    echo "Error catch: ".$e->getMessage();
}

AssertionError

如果你在php.ini里,把assert.exception设置成1,当断言失败的时候,你就会收到这个异常:

try {
    assert('1 > 2', '1 > 2, are your serious?');
}
catch(AssertionError $e) {
    echo $e->getMessage();
}

“如果我们在assert()里不设置错误信息,AssertError读不到错误信息的。”
最佳实践

ArithmeticError and DivisionByZeroError

ArithmeticError和算数运算有关。运算发生越界或者bit shift负数位数,都会导致发生ArithmeticError。例如下面这段代码就会导致“Bit shift by negative number”错误。

try {
    1 >> -1;
}
catch(ArithmeticError $e) {
    echo $e->getMessage();
}

而DivisionByZeroError则表示除数为0而导致的错误(无论我们使用 / % 或 intdiv(),只要除数为0,都会导致这个错误)。

TypeError

我们在前面的视频介绍过PHP 7的scalar type hints以及strict mode。无论是scalar type hints还是传统的type hints(class / interface / callable / array),只要类型不匹配type hints约束的时候,就会导致TypeErro异常。

try {
    1 >> -1;
}
catch(ArithmeticError $e) {
    echo $e->getMessage();
}

set_error_handler()

在PHP 7里,有一点是和PHP 5不兼容的,如果我们之前使用set_error_handler()处理catchable fatal error,在PHP 7里,这些error已经变成了engine exception,它们不会再被set_error_handler()处理。

自定义异常

尽管Throwable是PHP 7中的顶层异常接口,但当我们自定义异常的时候,却不能直接实现它。否则PHP会提示我们下面的错误:

class MyException implements Throwable {}

Fatal error: Class MyException cannot implement interface Throwable, extend Exception or Error instead

为了能正确处理异常行号、文件名和stack trace,我们只能从Exception或者Error派生自己的异常类。但是,我们可以拓展新的Throwable接口,并且实现其中的方法:

interface MyExceptionInterface extends Throwable { }

class MyError 
    extends Error implements MyExceptionInterface { }

脚本宝典总结

以上是脚本宝典为你收集整理的上手并过渡到PHP7(4)——取代fatal error的engine exceptions全部内容,希望文章能够帮你解决上手并过渡到PHP7(4)——取代fatal error的engine exceptions所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。