zoukankan      html  css  js  c++  java
  • 上手并过渡到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 { }
    

     

     
    原文:
    https://segmentfault.com/a/1190000004219265
     
  • 相关阅读:
    Linux开发初探
    Linux开发初探
    电脑使用说明书
    电脑使用说明书
    Delegates, Events, and Anonymous Methods 委托、事件与匿名方法
    CSS haslayout
    js与flash结合使用
    sgen.exe" exited with code 1.解决方法
    selenium
    selenium支付高版本的FireFox
  • 原文地址:https://www.cnblogs.com/chunguang/p/5538413.html
Copyright © 2011-2022 走看看