ZetCode

PHP try/catch/finally 语句

最后修改于 2025 年 4 月 16 日

PHP 的 trycatchfinally 语句对于异常处理至关重要。它们允许进行优雅的错误恢复和清理操作。这些结构有助于管理 PHP 中的运行时错误。

基本定义

try 块包含可能抛出异常的代码。catch 块处理从 try 块抛出的异常。

finally 块无论是否抛出异常都会执行代码。它是进行清理操作(如关闭文件或连接)的理想选择。

语法:try { code } catch (ExceptionType $e) { handle } finally { cleanup }。异常是代表执行过程中发生的错误的.*对象。

基本 try-catch

此示例演示了一个处理除零错误的简单 try-catch 块。

basic_try_catch.php
<?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 来处理不同的异常类型。

multiple_catch.php
<?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 进行清理操作。

finally_block.php
<?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 块始终会执行。

自定义异常

此示例展示了如何创建和抛出自定义异常。

custom_exception.php
<?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 块进行复杂的错误处理。

nested_try_catch.php
<?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 块中访问异常详细信息。

exception_info.php
<?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() 提供调用堆栈。

全局异常处理程序

此示例演示了如何设置全局异常处理程序。

global_handler.php
<?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");

代码设置了一个全局异常处理函数。此函数将捕获脚本中任何未捕获的异常。处理程序会记录错误并显示一条消息。全局处理程序对于集中错误日志记录和显示非常有用。

最佳实践

来源

PHP 异常处理文档

本教程介绍了 PHP 异常处理,并通过实际示例展示了 try、catch 和 finally 在各种场景下的用法。

作者

我叫 Jan Bodnar,我是一名热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在教学编程方面拥有十多年的经验。

列出 所有 PHP 教程