异常

PPG007 ... 2022-12-30 About 2 min

# 异常

like Java, try, catch, finally.

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
} catch (Exception|InvalidArgumentException $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "First finally.\n";
}

try {
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "Second finally.\n";
}

// 继续执行
echo "Hello World\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

从 PHP 7.1.0 起 catch 可以用竖线符(|) 指定多个异常。 如果在不同的类层次结构中,不同异常的异常需要用同样的方式处理,就特别适用这种方式。

从 PHP 8.0.0 起,捕获的异常不再强制要求指定变量名。 catch 代码块会在未指定时继续执行,只是无法访问到抛出的对象。

PHP 8.0.0 起,throw 关键词现在开始是表达式,可用于任何表达式上下文。在此之前,它是语句,必须独占一行。

如果在 try 或 catch 里遇到 return,仍然会执行 finally 里的代码。 而且,遇到 return 语句时,会先执行 finally 再返回结果。 此外,如果 finally 里也包含了 return 语句,将返回 finally 里的值。

# 全局异常处理

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}
set_exception_handler(function (Throwable $e) {
    echo 'wuhu' . "\n";
});
inverse(0);
1
2
3
4
5
6
7
8
9
10
11

# 扩展异常处理类

Warning

不能直接实现 Throwable 接口。

继承 Exception 类:

<?php
class MyException extends Exception
{
    public function __toString(): string
    {
        return self::class . ' ' . $this->message;
    }


}

try {
    throw new MyException("wuhu");
}catch (MyException $e) {
    echo $e . "\n";
}catch (Exception $e) {
    echo 'Exception' . "\n";
}finally {
    echo 'finally' . "\n";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Note

不能 复制 Exception 对象。尝试对 clone Exception 会导致 fatal E_ERROR 错误。

# 错误

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

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

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

Last update: December 30, 2022 03:19
Contributors: Koston Zhuang