异常处理

通用

异常 是指一些不寻常的条件,因为它超出了预期的正常行为。 例如,处理需要关键资源但资源不可用,以及检测计算超出范围的值。 因此,异常需要特殊处理。 本章介绍了如何创建和处理异常。

在运行时检测到异常条件时,会抛出异常。 指定的异常处理程序可以捕获抛出的异常并进行处理。 处理程序可能会完全从异常中恢复(允许脚本继续执行),它可能会执行一些恢复操作然后抛出异常以获取进一步帮助,或者它可能会执行一些清理操作并终止脚本。 异常可能是由引擎代为抛出,也可能是由脚本中的显式代码源代码抛出。

异常处理涉及使用以下关键字

  • try,它允许尝试包含一个或多个可能异常生成的try 块代码。
  • catch,它定义了用于处理从相应 try 块或它调用的某个函数抛出的特定类型异常的处理程序。
  • finally,它允许在 try 块中执行finally 块(例如,执行一些清理操作),无论该 try 块中是否发生异常。
  • throw,它从称为抛出点的位置生成给定类型的异常。

抛出异常时,将创建类型为 Exception(或其子类)的异常对象,并将其提供给可以捕获它的第一个 catch 处理程序。 异常对象除了包含其他信息外,还包含异常消息异常代码,处理程序可以使用它们来确定如何处理情况。

PHP 错误也可以通过类 ErrorException(不属于本规范)转换为异常。

Exception

Exception 是所有异常类型的基类。 该类定义如下

class Exception implements Throwable
{
  protected $message = 'Unknown exception';
  protected $code = 0;
  protected $file;
  protected $line;

  public function __construct($message = "", $code = 0,
               Throwable $previous = NULL);

  final private function __clone();
}

有关异常回溯和嵌套异常的信息,请参阅 追踪异常

有关基本接口的信息,请参阅 Throwable。 请注意,Throwable 中的方法在 Exception 类中被实现为 final,这意味着扩展类不能覆盖它们。

类成员定义如下

名称用途
$codeint;异常代码(由构造函数提供)
$filestring;生成异常的脚本名称
$lineint;生成异常的脚本中的源代码行号
$messagestring;异常消息(由构造函数提供)
__construct接受三个(可选)参数 - string:异常消息(默认为“”),int:异常代码(默认为 0),以及 Exception:链中的前一个异常(默认为 NULL
__clone存在以抑制异常对象的克隆

追踪异常

捕获异常时,类 Exception 中的 get* 函数提供有用的信息。 如果涉及一个或多个嵌套函数调用才能到达生成异常的位置,则也会保留这些调用的记录,并通过 getTrace 提供,称为*函数堆栈追踪*,或简称为*追踪*。

我们将脚本的顶层称为函数级 0。 函数级 1 是在从函数级 0 调用的任何函数内部。 函数级 2 是在从函数级 1 调用的任何函数内部,依此类推。 getTrace 方法返回一个数组。 在函数级 0 生成的异常不涉及任何函数调用,在这种情况下,getTrace 返回的数组为空。

getTrace 返回的数组中的每个元素都提供了有关给定函数级的信息。 我们将此数组称为追踪数组,并将此数组中的元素数量称为调用级。 追踪数组中每个元素的键的类型为 int,范围从 0 到调用级 - 1。 例如,当顶层脚本调用函数 f1,它调用函数 f2,它调用函数 f3,然后生成异常时,存在四个函数级,0-3,并且存在三组追踪信息,每个调用级一组。 也就是说,追踪数组包含三个元素,它们分别对应于函数调用的反向顺序。 例如,追踪数组[0] 用于调用函数 f3追踪数组[1] 用于调用函数 f2追踪数组[2] 用于调用函数 f1

追踪数组中的每个元素本身都是一个数组,它包含具有以下键值对的元素

值类型
“args”数组传递给函数的参数集
“class”字符串函数的父类名称
“file”字符串调用函数的脚本名称
“function”字符串函数或类方法的名称
“line”int调用函数的源代码中的行号
“object”对象当前对象
“type”字符串调用类型;-> 表示实例方法调用,:: 表示静态方法调用,表示普通函数调用,返回空字符串("")。

args 的值是另一个数组,我们将其称为参数数组。 该数组包含一组值,这些值直接对应于传递给相应函数的参数集。 关于元素顺序,参数数组[0] 对应于最左边的参数,参数数组[1] 对应于下一个右侧的参数,依此类推。

请注意,只报告传递给函数的实际参数。 考虑一个函数为参数定义了默认参数值的例子。 如果调用该函数而不为具有默认值的参数提供参数,则参数数组中不存在相应的参数。 只有在函数调用站点存在的参数的值才会记录在参数数组中。

另请参阅库函数 debug_backtracedebug_print_backtrace

用户定义的异常类

异常类只需继承类 Exception 即可定义。 但是,由于该类的 __clone 方法被声明为 final,因此无法克隆异常对象。

定义异常类时,通常,其构造函数会将其第一个操作作为调用父类构造函数,以确保新对象的基类部分得到适当初始化。 它们还经常提供对 __toString() 的增强实现。