异常处理
通用
异常 是指一些不寻常的条件,因为它超出了预期的正常行为。 例如,处理需要关键资源但资源不可用,以及检测计算超出范围的值。 因此,异常需要特殊处理。 本章介绍了如何创建和处理异常。
在运行时检测到异常条件时,会抛出异常。 指定的异常处理程序可以捕获抛出的异常并进行处理。 处理程序可能会完全从异常中恢复(允许脚本继续执行),它可能会执行一些恢复操作然后抛出异常以获取进一步帮助,或者它可能会执行一些清理操作并终止脚本。 异常可能是由引擎代为抛出,也可能是由脚本中的显式代码源代码抛出。
异常处理涉及使用以下关键字
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
,这意味着扩展类不能覆盖它们。
类成员定义如下
名称 | 用途 |
---|---|
$code | int ;异常代码(由构造函数提供) |
$file | string ;生成异常的脚本名称 |
$line | int ;生成异常的脚本中的源代码行号 |
$message | string ;异常消息(由构造函数提供) |
__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_backtrace
和 debug_print_backtrace
。
用户定义的异常类
异常类只需继承类 Exception
即可定义。 但是,由于该类的 __clone
方法被声明为 final
,因此无法克隆异常对象。
定义异常类时,通常,其构造函数会将其第一个操作作为调用父类构造函数,以确保新对象的基类部分得到适当初始化。 它们还经常提供对 __toString()
的增强实现。