上手并过渡到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(1)——基于Homestead的PHP7和XDdebug环境
PHP7 up and running 泊学实操视频泊学原文链接PHP7, Xdebug and Homestead 在经历了13个RC版本之后,PHP 7终于来了.在我们上手评估PHP 7的新特性之 ...
- 上手并过渡到PHP7(3)——Uniform Variable Syntax到底统一了什么
PHP7 up and running 泊学原文链接泊学实操视频 Uniform Variable Syntax 在PHP 7提出Uniform Variable Syntax之前,我们大多数人可能都 ...
- 上手并过渡到PHP7(5)——轻量级“集合”迭代器-Generator
轻量级“集合”迭代器-Generator泊学视频链接泊阅文档链接Generator是PHP 5.5加入的新语言特性.但是,它似乎并没有被很多PHP开发者广泛采用.因此,在我们了解PHP 7对Gener ...
- 上手并过渡到PHP7(2)——必须传递int, string, bool参数?没问题
Type hints, Type safe 泊学实操视频 泊学原文链接PHP 7中最引人注目的新特性之一,无疑是Scalar type hints.我们可以在函数参数和返回值中使用scalar typ ...
- VS2010遇到fatal error C1083: 无法打开预编译头文件:“xxx.pch”: No such file or directory
对C++和VS2010非常不熟悉,但是无奈赶着项目,只能看了点基础就上手,然后就碰到这个问题了. 原因分析: http://bbs.csdn.net/topics/340191697?page=1 编 ...
- PHP Fatal error: Call to undefined function mysql_connect() 错误解释
我使用的是5.6.11版本的php 刚开始以为编译参数加了--with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd,就可以不能安装mysql了. 但是使用了mysq ...
- PHP Fatal error: Uncaught Error: Call to undefined function pcntl_fork().. 开启php pcntl扩展实现多进程
在使用函数pcntl_fork()时报错 Fatal error: Uncaught Error: Call to undefined function pcntl_fork()....,原因是没有 ...
- php捕获Fatal error错误与异常处理
php中的错误和异常是两个不同的概念. 错误:是因为脚本的问题,比如少写了分号,调用未定义的函数,除0,等一些编译语法错误. 异常:是因为业务逻辑和流程,不符合预期情况,比如验证请求参数,不通过就用 ...
- fatal error C1045: 编译器限制 : 链接规范嵌套太深
前言 我相信你是遇到了同样的问题.通过搜索引擎来到这里的.为了不耽误排查问题的时间,我提前说明一下这篇文章所描述的问题范畴: 我遇到的问题和 c++ 模板相关: 如果我减少传递的参数的话,是有可能避免 ...
随机推荐
- Android开发学习之对话框浅析
对话框式程序运行中弹出的窗口.Android系统中有四种默认的对话框:警告对话框AlertDialog.进度对话框ProgressDialog.日期选择对话框DatePickerDialog以及时间选 ...
- pcurl 学习 http文件下载及写入空设备文件实例
import pycurl import sys import os import random import string import time class Transaction(object) ...
- RHCE7 管理I-12归档文件并在Linux系统间复制文件
tar命令使用 默认tar只有归档的功能,没有压缩功能 tar [option...] [file]... -c,--create 创建 -x,--extract,--get 解压 -t, ...
- Unix环境高级编程(十三)守护进程
守护进程也称为精灵进程是一种生存期较长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.他们常常在系统引导装入时启动,在系统关闭时终止.unix系统有很多守护进程,大多数 ...
- 修改Excel默认模版(启动模版和新建Sheet模版)
Office 2013 1. C:\Windows\ShellNew\EXCEL12.XLSX 设置好格式后另存为, 然后复制过来覆盖掉,如果覆盖不了,注意修改所有者权限 2. 新建文件保存为模版文 ...
- Spring中三种配置Bean的方式
Spring中三种配置Bean的方式分别是: 基于XML的配置方式 基于注解的配置方式 基于Java类的配置方式 一.基于XML的配置 这个很简单,所以如何使用就略掉. 二.基于注解的配置 Sprin ...
- C/C++ 数据结构之算法(面试)
数据结构中的排序算法. 排序算法的相关知识: (1)排序的概念:所谓排序就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来. (2)稳定的排序方法:在待排序的文件中,若存在多个关键字相同的 ...
- LINUX下添加磁盘空间的方法详解
给Linux系统添加磁盘空间在工作会经常遇到. 在添加第二块磁盘一般系统默认为hdb(IDE硬盘)sdb(SCSI 硬盘),以hdb为例. linux-isep:~ # fdisk /dev/hdb ...
- [k8s]容器化node-expolore(9100)+cadvisor(8080)+prometheus(9090) metric搜集,grafana展示
Prometheus 的核心,多维数据模型 传统监控工具统计数据方式 指标多 - 需求1,统计app1-3,的(总)内存,则定义3个指标 container.memory_usage_bytes.we ...
- [na][QoS]cisco3560限速配置案例-收集于网工泡泡
网络中常用到这些:CISCO和H3C-MAC过滤+端口限速+端口镜像+端口隔离 不同的方式不同的思想:嘎嘎 其他各个厂商的限速链接:http://pan.baidu.com/s/1hrIMoSG 密码 ...