程序员书籍笔记 程序员书籍笔记
  • JavaScript
  • HTML/CSS
  • PHP
  • Python
  • Go
  • 数据库
  • 容器
  • 微服务
  • 消息队列
  • 搜索引擎
  • 大数据
  • 鸟哥Linux私房菜
其他
  • 大数据
  • 深度学习
APP下载 (opens new window)
GitHub (opens new window)
  • JavaScript
  • HTML/CSS
  • PHP
  • Python
  • Go
  • 数据库
  • 容器
  • 微服务
  • 消息队列
  • 搜索引擎
  • 大数据
  • 鸟哥Linux私房菜
其他
  • 大数据
  • 深度学习
APP下载 (opens new window)
GitHub (opens new window)
  • PHP

    • 官方文档

      • 基本语法
      • 函数
      • 类与对象
      • 命名空间
      • 错误和异常
        • 错误处理
        • 异常
      • 生成器和注解
      • 引用和预定义
      • 上下文与支持的协议
      • 安全和特点
  • Python

  • Go

  • 后端
  • PHP
  • 官方文档
小游
2021-04-26

错误和异常

# 错误处理

PHP 遇到一系列内部错误时,会报告出来作为应对。 它可以用来标示不同的情况,可以要求将错误显示出来或记录到日志中。

每个 PHP 产生的错误都包含了类型。可查看 错误类型清单 (opens new window),它附带了不同类型行为的简短描述和 产生的原因。

如果 PHP 默认错误处理器还不能满足要求,用户可以通过 set_error_handler() (opens new window) 设置自定义错误处理器,可处理很多类型的错误。 虽然有些类型的错误不能通过这种方式处理,但能处理的类型可以用脚本合适的方式处理: 例如为用户显示自定义错误页面,同时以一种比日志更直接的方式上报错误,例如发送邮件。

PHP7后,我们可以使用try/catch来进行错误处理

PHP 7 改变了大多数错误的报告方式。不同于传统(PHP 5)的错误报告机制,现在大多数错误被作为 Error (opens new window) 异常抛出。

这种 Error (opens new window) 异常可以像 Exception (opens new window) 异常一样被第一个匹配的 try / catch 块所捕获。如果没有匹配的 catch (opens new window) 块,则调用异常处理函数(事先通过 set_exception_handler() (opens new window) 注册)进行处理。 如果尚未注册异常处理函数,则按照传统方式处理:被报告为一个致命错误(Fatal Error)。

Error (opens new window) 类并非继承自 Exception (opens new window) 类,所以不能用 catch (Exception $e) { ... } 来捕获 Error (opens new window)。你可以用 catch (Error $e) { ... },或者通过注册异常处理函数( set_exception_handler() (opens new window))来捕获 Error (opens new window)。

# 异常

用户可以用自定义的异常处理类来扩展 PHP 内置的异常处理类。以下的代码说明了在内置的异常处理类中,哪些属性和方法在子类中是可访问和可继承的。PHP内置的异常类

<?php
class Exception extends Throwable
{
    protected $message = 'Unknown exception';   // 异常信息
    private   $string;                          // __toString 的缓存
    protected $code = 0;                        // 用户自定义异常错误码
    protected $file;                            // 发生异常的源文件名
    protected $line;                            // 发生异常的源代码行号
    private   $trace;                           // backtrace
    private   $previous;                        // 如果是嵌套异常,则是之前的 exception

    public function __construct($message = null, $code = 0, Exception $previous = null);

    final private function __clone();           // Inhibits cloning of exceptions.

    final public  function getMessage();        // 异常信息
    final public  function getCode();           // 异常错误码
    final public  function getFile();           // 发生异常的源文件名
    final public  function getLine();           // 发生异常的源代码行号
    final public  function getTrace();          // backtrace() 数组
    final public  function getPrevious();       // 之前的 exception
    final public  function getTraceAsString();  // 已格成化成字符串的 getTrace() 信息

    // Overrideable
    public function __toString();               // 可输出的格式化后的字符串
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

我们可以使用下面这几种方法来进行处理

<?php
/**
 * 自定义一个异常处理类
 */
class MyException extends Exception
{
    // 重定义构造器使 message 变为必须被指定的属性
    public function __construct($message, $code = 0, Exception $previous = null) {
        // 这里写用户的代码

        // 确保所有变量都被正确赋值
        parent::__construct($message, $code, $previous);
    }

    // 自定义字符串输出的格式
    public function __toString() {
        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }

    public function customFunction() {
        echo "A custom function for this type of exception\n";
    }
}


/**
 * 创建一个类,测试该 exception 类
 */
class TestException
{
    public $var;

    const THROW_NONE    = 0;
    const THROW_CUSTOM  = 1;
    const THROW_DEFAULT = 2;

    function __construct($avalue = self::THROW_NONE) {

        switch ($avalue) {
            case self::THROW_CUSTOM:
                // 抛出自定义异常
                throw new MyException('1 is an invalid parameter', 5);
                break;

            case self::THROW_DEFAULT:
                // 抛出默认的异常
                throw new Exception('2 is not allowed as a parameter', 6);
                break;

            default: 
                // 没有异常的情况下,创建一个对象
                $this->var = $avalue;
                break;
        }
    }
}


// 例子 1
try {
    $o = new TestException(TestException::THROW_CUSTOM);
} catch (MyException $e) {      // 捕获异常
    echo "Caught my exception\n", $e;
    $e->customFunction();
} catch (Exception $e) {        // 被忽略
    echo "Caught Default Exception\n", $e;
}

// 继续执行后续代码
var_dump($o); // Null
echo "\n\n";


// 例子 2
try {
    $o = new TestException(TestException::THROW_DEFAULT);
} catch (MyException $e) {      //  不能匹配异常的种类,被忽略
    echo "Caught my exception\n", $e;
    $e->customFunction();
} catch (Exception $e) {        // 捕获异常
    echo "Caught Default Exception\n", $e;
}

// 执行后续代码
var_dump($o); // Null
echo "\n\n";


// 例子 3
try {
    $o = new TestException(TestException::THROW_CUSTOM);
} catch (Exception $e) {        // 捕获异常
    echo "Default Exception caught\n", $e;
}

// 执行后续代码
var_dump($o); // Null
echo "\n\n";


// 例子 4
try {
    $o = new TestException();
} catch (Exception $e) {        // 没有异常,被忽略
    echo "Default Exception caught\n", $e;
}

// 执行后续代码
var_dump($o); // TestException
echo "\n\n";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
编辑 (opens new window)
上次更新: 2021/05/08, 22:02:42
命名空间
生成器和注解

← 命名空间 生成器和注解→

Theme by Vdoing | Copyright © 2021-2021 小游
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式