PHP try/catch/finally 语句
最后修改于 2025 年 4 月 16 日
PHP 的 try、catch 和 finally 语句对于异常处理至关重要。它们允许进行优雅的错误恢复和清理操作。这些结构有助于管理 PHP 中的运行时错误。
基本定义
try 块包含可能抛出异常的代码。catch 块处理从 try 块抛出的异常。
finally 块无论是否抛出异常都会执行代码。它是进行清理操作(如关闭文件或连接)的理想选择。
语法:try { code } catch (ExceptionType $e) { handle } finally { cleanup }。异常是代表执行过程中发生的错误的.*对象。
基本 try-catch
此示例演示了一个处理除零错误的简单 try-catch 块。
<?php
declare(strict_types=1);
try {
$result = 10 / 0;
echo "Result: $result";
} catch (DivisionByZeroError $e) {
echo "Error: Cannot divide by zero";
}
代码尝试在 try 块中进行除零操作。这会抛出 DivisionByZeroError。catch 块会捕获此特定异常类型。错误消息会显示出来,而不是导致程序崩溃。
多个 catch 块
此示例展示了如何使用多个 catch 来处理不同的异常类型。
<?php
declare(strict_types=1);
try {
$file = fopen("nonexistent.txt", "r");
$content = fread($file, 100);
fclose($file);
} catch (RuntimeException $e) {
echo "Runtime error: " . $e->getMessage();
} catch (Exception $e) {
echo "General error: " . $e->getMessage();
}
代码尝试打开一个不存在的文件。这会抛出 RuntimeException。第一个 catch 专门处理运行时错误。第二个 catch 捕获所有其他异常。应该先捕获更具体的异常。
Finally 块
此示例演示了如何使用 finally 进行清理操作。
<?php
declare(strict_types=1);
$resource = null;
try {
$resource = fopen("data.txt", "w");
fwrite($resource, "Hello World");
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
} finally {
if ($resource) {
fclose($resource);
echo "Resource closed";
}
}
代码在 try 块中打开文件并向其写入。finally 块确保文件无论是否发生异常都会被关闭。这可以防止资源泄露。finally 块始终会执行。
自定义异常
此示例展示了如何创建和抛出自定义异常。
<?php
declare(strict_types=1);
class InvalidEmailException extends Exception {}
function validateEmail(string $email): bool {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidEmailException("Invalid email format");
}
return true;
}
try {
validateEmail("invalid-email");
} catch (InvalidEmailException $e) {
echo "Validation error: " . $e->getMessage();
}
代码定义了一个自定义的 InvalidEmailException 类。validateEmail 函数在电子邮件无效时抛出此异常。catch 块会处理此特定异常类型。自定义异常可以使错误处理更清晰。
嵌套 try-catch
此示例演示了如何使用嵌套的 try-catch 块进行复杂的错误处理。
<?php
declare(strict_types=1);
try {
try {
$result = 10 / 0;
} catch (DivisionByZeroError $e) {
throw new Exception("Calculation failed", 0, $e);
}
} catch (Exception $e) {
echo "Outer catch: " . $e->getMessage();
echo "Previous: " . $e->getPrevious()->getMessage();
}
内部 try 尝试进行除零操作。内部 catch 将错误转换为更通用的 Exception。外部 catch 会处理此异常,并通过 getPrevious() 访问原始错误。这允许进行错误包装和传播。
异常信息
此示例展示了如何在 catch 块中访问异常详细信息。
<?php
declare(strict_types=1);
try {
$array = [1, 2, 3];
echo $array[5];
} catch (OutOfBoundsException $e) {
echo "Error: " . $e->getMessage() . "\n";
echo "File: " . $e->getFile() . "\n";
echo "Line: " . $e->getLine() . "\n";
echo "Trace: " . $e->getTraceAsString() . "\n";
}
代码尝试访问无效的数组索引。catch 块展示了如何获取详细的错误信息。getMessage() 返回错误描述。getFile() 和 getLine() 显示错误发生的位置。getTraceAsString() 提供调用堆栈。
全局异常处理程序
此示例演示了如何设置全局异常处理程序。
<?php
declare(strict_types=1);
function globalExceptionHandler(Throwable $e) {
echo "Global handler caught: " . $e->getMessage();
error_log("Uncaught exception: " . $e->getMessage());
}
set_exception_handler('globalExceptionHandler');
// This exception won't be caught by any try-catch
throw new Exception("Something went wrong");
代码设置了一个全局异常处理函数。此函数将捕获脚本中任何未捕获的异常。处理程序会记录错误并显示一条消息。全局处理程序对于集中错误日志记录和显示非常有用。
最佳实践
- 特定捕获:先捕获特定的异常类型。
- 清理:使用 finally 进行资源清理操作。
- 日志记录:记录异常以供调试。
- 自定义异常:创建特定于域的异常。
- 优雅恢复:在可能的情况下提供备用行为。
来源
本教程介绍了 PHP 异常处理,并通过实际示例展示了 try、catch 和 finally 在各种场景下的用法。
作者
列出 所有 PHP 教程。