PHP 异常处理及内部错误类

PHP5引入了异常。

异常 是实例化自 内置的Exception类(或其他继承类)的特殊对象。Exception类型的对象可以存放和报告错误信息。

Exception类的构造方法接受两个可选参数 —— 一个消息字符串和一个错误码。该类提供了一些有用的方法来帮助我们分析错误情况。

异常类中的公开方法
方法 说明
getMessage() 得到传递给构造方法的消息字符串
getCode() 得到传递给构造方法的错误代码(整数)
getFile() 得到发生异常的文件
getLine() 得到发生异常的行号
getPrevious() 得到一个嵌套异常对象
getTrace()

得到一个多维数组,其中保存了引发异常的方法调用的跟踪信息,包括方法、类、

文件和参数数据

getTraceAsString() 得到getTrace()方法返回的数据的字符串版本
__toString()

当Exception对象被用作字符串时,该方法会被自动调用。它会返回一个描述异常

细节的字符串

1.

抛出异常

可以使用throw和Exception对象一起来抛出异常,这会导致当前方法的执行被终止,并将错误处理的责任转回给调用方代码。

那么如何让客户端代码知道异常抛出时应该如何处理呢?当我们调用一个可能抛出异常的方法时,可以将方法放在try字句中。每一个try子句之后至少跟着一个catch子句才能处理错误

1 <?php
2 try {
3     echo 'abc';
4     throw new Exception('抛出异常信息');
5     echo 'def';
6 } catch (\Exception $e) {
7     echo $e->getMessage();
8 }
9 // 输出:abc抛出异常信息

可以看到,catch子句类似于方法声明。当异常抛出后,调用作用域内的catch子句会被调用。Exception对象会作为参数变量自动传递给catch子句。

当有异常抛出时,会终止执行抛出异常的方法,try语句会直接将程序执行的控制权转交给catch语句。

2.

子类化异常

可以通过继承Exception类来创建用户自定义的异常。之所以要这么做,理由有二:一是扩展异常类的功能,二是子类定义新的异常类型能帮我们处理错误。

实际上,可以在try语句中编写多个catch语句。究竟调用哪个catch语句,取决于被抛出的异常的类型,以及参数列表中的类类型提示。下面定义了一些简单的Exception类的子类。

 1 <?php
 2 class AException extends \Exception
 3 {
 4 }
 5 class BException extends \Exception
 6 {
 7 }
 8 try {
 9     throw new BException('抛出AException类错误信息');
10 } catch (\AException $e) {
11     // AException类异常
12     echo 'A --- ' . $e->getMessage();
13 } catch (\BException $e) {
14     // BException类异常
15     echo 'B --- ' . $e->getMessage();
16 } catch (\Exception $e) {
17     // 备用捕捉器
18     echo $e->getMessage();
19 }
20 // 输出:B --- 抛出AException类错误信息

如以上代码所示,究竟调用哪一个catch子句,却决于被抛出的异常类型。

由于第一个匹配到的catch子句会被执行,请将最通用的类型的catch子句放在最后面,将最特化类型的子句放在最前面。

如果将用于捕捉Exception的catch子句放在了捕捉AExceptioin和BException的子句前面,那么这两个子句将永远不会被调用。因为这两个类型都属于Exception类型,它们会匹配第一个catch子句。

在异常处理中加上一个“备用”的catch子句是一个好习惯,能防止我们在开发过程中向代码加入新的异常却又忘记处理。


注意:如果编写了备用的“catch”语句,那么应当确保已经对那些会在大多数实例中发生的异常进行了处理,否则将导致难以跟踪调试的BUG。


3.

在try/catch语句后使用finally完成清理工作

PHP5.5引入了一个新的子句finally。无论try是否抛出了异常,finally子句都会被执行

 1 <?php
 2 try {
 3     throw new Exception('抛出错误信息');
 4 } catch (\Exception $e) {
 5     // 备用捕捉器
 6     echo $e->getMessage();
 7 } finally {
 8     echo ' 执行finally子句';
 9 }
10 // 输出:抛出错误信息 执行finally子句

注意:如果在try或catch代码块中调用了die()或exit(),那么程序就会终止。finally子句也就不会执行了


 4.内部错误类

try和catch子句主要针对的是PHP代码,内部生成的错误会维护它们自己的逻辑。

PHP7引入了Error类,可以让我们自己来管理核心错误。Error类和Exception类实现了同一个内置接口Throwable。因此,Error类也可以调用Exception类的方法

1 try {
2     eval('abc');
3 } catch (\Exception $e) {
4     echo '程序不会走这';
5 } catch (\Error $e) {
6     echo get_class($e) . " / " . $e->getMessage();
7 }
8 // 结果:ParseError / syntax error, unexpected end of file

Error类是针对独立的错误类型进行子类化的,比如上面代码,错误类型为ParseError。可以在catch子句中通过指定Error这个父类或是它的子类来捕捉相匹配的内部错误。

内置的Error子类如下:

错误 说明
ArithmeticError 在发生与数学计算(特别是位运算)相关的错误时被抛出
AssertionError 当assert()语言结构(调试中)断言失败时被抛出
DivisionByZeroError 进行除零计算时被抛出
ParseError 在运行时解析PHP(如使用eval())出错时被抛出
TypeError 当错误类型的参数被传递给方法,方法返回一个错误类型的参数,或是传递给方法的参数的数量不正确时被抛出
posted @ 2020-11-18 22:14  九鹤  阅读(202)  评论(0编辑  收藏  举报