资讯专栏INFORMATION COLUMN

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

mylxsw / 3021人阅读

摘要:上手并过渡到取代的泊学原文链接泊学代码秀视频自从以来,的错误处理几乎就是一成不变的。在中,这个尴尬的现状,终于被彻底改变了。无论是还是传统的,只要类型不匹配约束的时候,就会导致异常。

上手并过渡到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 { }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21292.html

相关文章

  • PHP 错误与异常

    摘要:但异常捕获后程序可以继续执行,而真正的错误出现后程序就必须终止异常可以使用来捕获捕获,捕获之后后续代码可以继续执行而错误是无法使用捕获的如果抛出了异常,就必须捕获它否则程序终止执行。 PHP错误级别 Parse error > Fatal Error > Waning > Notice > Deprecated Deprecated 最低级别的错误(不推荐,不建议)使用一些过期函数的...

    longmon 评论0 收藏0
  • PHP7新特性介绍

    摘要:截止到目前为止,官方已经发布了的版本,距离发布第一个正式版本不会很远了现在来说的重大特性肯定已经是定型了,不会再有什么变动了。 截止到目前为止,PHP官方已经发布了php7的RC7版本,距离发布第一个正式版本不会很远了!现在来说php7的重大特性肯定已经是定型了,不会再有什么变动了。后续一些版本的迭代主要也就是修修bug,优化之类的。下面就来说话我们一直期待的php7会有那些主要的变化...

    klivitamJ 评论0 收藏0
  • PHP7中异常与错误处理与之前版本对比

    先上代码 ECHO PHP_VERSION.PHP_EOL; function add (int $left,int $right){ return $left+$right; } try { echo add(left, right); } catch (Exception $e) { // Handle exception } catch (Error $e) { //...

    wemallshop 评论0 收藏0
  • PHP 7.1 新特性一览

    摘要:版本发布在即,本文整理一下中的一些新特性以供了解。所有内容均选自官方文档。可空类型可空类型主要用于参数类型声明和函数返回值声明。主要的两种形式如下从例子很容易理解,所指的就是通过的形式表明函数参数或者返回值的类型要么为指定类型,要么为。 PHP 7.1 release版本发布在即,本文整理一下 7.1 中的一些新特性以供了解。所有内容均选自官方 RFC 文档。 可空类型 可空类型主要用...

    timger 评论0 收藏0
  • 上手过渡PHP7(5)——轻量级“集合”迭代器-Generator

    摘要:轻量级集合迭代器泊学视频链接泊阅文档链接是加入的新语言特性。接下来,我们可以像访问一个普通集合一样使用现在重新执行我们的文件,就不会再报错了。简单来说,就是一个轻量级的,可以记住自身状态的集合迭代器。 轻量级集合迭代器-Generator泊学视频链接泊阅文档链接Generator是PHP 5.5加入的新语言特性。但是,它似乎并没有被很多PHP开发者广泛采用。因此,在我们了解PHP 7对...

    wupengyu 评论0 收藏0

发表评论

0条评论

mylxsw

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<