bte365娱乐线

PHP: 异常

发布时间 2026-06-21 22:08:44 作者 admin 阅读 5644

异常

目录扩展(extend)异常处理类

PHP 有一个和其他语言相似的异常模型。在 PHP 里可以 throw 并捕获(catch)异常。为了捕获潜在的异常,代码会包含在

try 块里。每个 try 都必须至少有一个相应的 catch 或 finally 块。

如果抛出异常的函数作用域内没有 catch 块,异常会沿调用栈“向上冒泡”,直到找到匹配的 catch 块。沿途会执行所有遇到的

finally 块。在没有设置全局异常处理程序时,如果调用栈向上都没有遇到匹配的 catch,程序会抛出 fatal 错误并终止。

抛出的对象必须是 instanceof Throwable。尝试抛出其他对象会导致 PHP Fatal 错误。

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

catch

catch 定义了处理抛出异常的方式。

catch 块定义了它能处理的异常/错误的类型,并可以选择将异常赋值到变量中。

(在 PHP 8.0.0 之前的版本中必须要赋值到变量)

如果遇到抛出对象的类型匹配了首个 catch 块的异常或错误,将会处理该对象。

可用多个 catch 捕获不同的异常类。

正常情况下(try 代码块里没有抛出异常)会在最后一个定义的 catch 后面继续执行。

catch 代码块里也可以 throw 或者重新抛出异常。

不抛出的话,会在触发的 catch 后面继续执行。

当 PHP 抛出一个异常时,将不会执行后续的代码语句,并会尝试查找首个匹配的 catch 代码块。

如果没有用 set_exception_handler() 设置异常处理函数,

PHP 会在异常未被捕获时产生 Fatal 级错误,提示 "Uncaught Exception ..."

消息。

从 PHP 7.1.0 起 catch 可以用竖线符(|) 指定多个异常。

如果在不同的类层次结构中,不同异常的异常需要用同样的方式处理,就特别适用这种方式。

从 PHP 8.0.0 起,捕获的异常不再强制要求指定变量名。

catch 代码块会在未指定时继续执行,只是无法访问到抛出的对象。

finally

finally 代码块可以放在 catch 之后,或者直接代替它。

无论是否抛出了异常,在 try 和 catch 之后、在执行后续代码之前,

放在 finally 里的代码总是会执行。

值得注意的是 finally 和 return 语句之间存在相互影响。

如果在 try 或 catch 里遇到 return,仍然会执行 finally 里的代码。

而且,遇到 return 语句时,会先执行 finally 再返回结果。

此外,如果 finally 里也包含了 return 语句,将返回 finally 里的值。

另一个值得注意的交互是发生在 try 块内抛出的异常与 finally

块内抛出的异常之间。如果两个块都抛出异常,则会传播来自 finally

块的异常,而来自 try 块的异常将作为其前一个异常。

全局异常处理程序

当允许异常冒泡到全局作用域时,它可以被全局异常处理器捕获到。

set_exception_handler()

可以设置一个函数,在没有调用其他块时代替 catch。

在本质上,实现的效果等同于整个程序被 try-catch 包裹起来,

而该函数就是 catch。

注释

注意:

PHP 内部函数主要使用 错误报告,

只有一些现代 面向对象 的扩展使用异常。

不过,错误很容易用 ErrorException

转化成异常。

然而,这个技术方案仅适用非 Fatal 级的错误。

示例 #1 将错误报告转成异常

function exceptions_error_handler($severity, $message, $filename, $lineno) {

throw new ErrorException($message, 0, $severity, $filename, $lineno);

}

set_error_handler('exceptions_error_handler');

?>

小技巧

PHP 标准库(SPL)

提供了大量的 标准内置异常。

示例

示例 #2 抛出一个异常

function inverse($x) {

if (!$x) {

throw new Exception('Division by zero.');

}

return 1/$x;

}

try {

echo inverse(5) . "\n";

echo inverse(0) . "\n";

} catch (Exception $e) {

echo 'Caught exception: ', $e->getMessage(), "\n";

}

// 继续执行

echo "Hello World\n";

?>

以上示例会输出:

0.2

Caught exception: Division by zero.

Hello World

示例 #3 带 finally 块的异常处理

function inverse($x) {

if (!$x) {

throw new Exception('Division by zero.');

}

return 1/$x;

}

try {

echo inverse(5) . "\n";

} catch (Exception $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";

?>

以上示例会输出:

0.2

First finally.

Caught exception: Division by zero.

Second finally.

Hello World

示例 #4 finally 和 return 相互之间的影响

function test() {

try {

throw new Exception('foo');

} catch (Exception $e) {

return 'catch';

} finally {

return 'finally';

}

}

echo test();

?>

以上示例会输出:

finally

示例 #5 异常嵌套

class MyException extends Exception { }

class Test {

public function testing() {

try {

try {

throw new MyException('foo!');

} catch (MyException $e) {

// 重新 throw

throw $e;

}

} catch (Exception $e) {

var_dump($e->getMessage());

}

}

}

$foo = new Test;

$foo->testing();

?>

以上示例会输出:

string(4) "foo!"

示例 #6 多个异常的捕获处理

class MyException extends Exception { }

class MyOtherException extends Exception { }

class Test {

public function testing() {

try {

throw new MyException();

} catch (MyException | MyOtherException $e) {

var_dump(get_class($e));

}

}

}

$foo = new Test;

$foo->testing();

?>

以上示例会输出:

string(11) "MyException"

示例 #7 忽略捕获的变量

仅仅在 PHP 8.0.0 及以上版本有效

function test() {

throw new SpecificException('Oopsie');

}

try {

test();

} catch (SpecificException) {

print "A SpecificException was thrown, but we don't care about the details.";

}

?>

以上示例会输出:

A SpecificException was thrown, but we don't care about the details.

示例 #8 以表达式的形式抛出

仅仅在 PHP 8.0.0 及以上版本有效

class SpecificException extends Exception {}

function test() {

do_something_risky() or throw new Exception('It did not work');

}

function do_something_risky() {

return false; // 模拟失败

}

try {

test();

} catch (Exception $e) {

print $e->getMessage();

}

?>

以上示例会输出:

It did not work

示例 #9 try 和 finally 中的异常

try {

try {

throw new Exception(message: 'Third', previous: new Exception('Fourth'));

} finally {

throw new Exception(message: 'First', previous: new Exception('Second'));

}

} catch (Exception $e) {

var_dump(

$e->getMessage(),

$e->getPrevious()->getMessage(),

$e->getPrevious()->getPrevious()->getMessage(),

$e->getPrevious()->getPrevious()->getPrevious()->getMessage(),

);

}

以上示例会输出:

string(5) "First"

string(6) "Second"

string(5) "Third"

string(6) "Fourth"

相关推荐

M4A4还是M4A1-S:一场关于CT步枪的爱恨情仇

无论是在CSGO时代以及目前版本中,CT方的步枪选择一直是玩家们津津乐道的话题。M4A4和M4A1-S这两把枪械,在游戏的历史长河中上演了一场精彩的

07-25 分类 365bet世界杯

真菌传染的方式有哪些

真菌传染是指由真菌引起的疾病在人体之间传播的过程。真菌传染通常是通过接触感染源或者接触感染源所带来的环境进行传播的,下面是真菌

08-28 分类 super365体育官网下载

女式内裤

女式内裤蕾丝漂亮又小巧的女士内裤。类型内衣物 女式内裤(英语:Panties)是指专为女性设计的内裤,一般指女短内裤。女式内裤大多是紧身

07-07 分类 super365体育官网下载

总岔气挂什么科检查

总岔气可以挂呼吸内科、消化内科、胸外科、普外科、急诊科进行检查和治疗。如果症状持续或伴有其他不适,建议及时就医以确定具体原因并

12-31 分类 bte365娱乐线

M4A4还是M4A1-S:一场关于CT步枪的爱恨情仇

无论是在CSGO时代以及目前版本中,CT方的步枪选择一直是玩家们津津乐道的话题。M4A4和M4A1-S这两把枪械,在游戏的历史长河中上演了一场精彩的

07-25 分类 365bet世界杯

华为手机5寸屏有哪款

随着移动互联网的快速发展,智能手机已经成为人们日常生活中不可或缺的载体。5寸屏幕是智能手机市场中最受欢迎的屏幕尺寸之一,因为它既

09-15 分类 super365体育官网下载

手机qq群送花流程

手机qq群怎么送花? 1、 首先,请大家将自己手机上安装的手机QQ更新到最新版本,因为只有最新版本的手机QQ才可以享受到送花功能应用,然后

11-29 分类 super365体育官网下载