ZetCode

PHP throw 语句

最后修改于 2025 年 4 月 16 日

PHP throw 关键字用于在代码中手动触发异常。 异常是一种强大的错误处理机制,允许您优雅地处理错误。 throw 语句与 try-catch 块一起使用,以实现可靠的错误处理。

基本定义

throw 语句在 PHP 中引发异常。 当抛出时,执行停止,PHP 查找匹配的 catch 块。 异常必须是实现 Throwable 接口的对象。

内置的 Exception 是 PHP 中所有异常的基类。 您还可以通过扩展 Exception 来创建自定义异常类。 异常会通过调用堆栈冒泡,直到被捕获。

语法:throw new Exception("错误消息");。 throw 关键字后跟一个异常对象。 异常消息应清楚地描述错误。

基本 throw 示例

此示例演示了 throw 关键字的最简单用法。

basic_throw.php
<?php

function divide($numerator, $denominator) {
    if ($denominator == 0) {
        throw new Exception("Division by zero");
    }
    return $numerator / $denominator;
}

try {
    echo divide(10, 0);
} catch (Exception $e) {
    echo "Caught exception: " . $e->getMessage();
}

当尝试除以零时,代码会抛出异常。 try 块包含可能抛出异常的代码。 catch 块处理异常并显示其消息。 这可以防止致命错误。

自定义异常类

此示例演示如何创建和使用自定义异常类。

custom_exception.php
<?php

class InvalidEmailException extends Exception {}

function validateEmail($email) {
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        throw new InvalidEmailException("Invalid email format");
    }
    return true;
}

try {
    validateEmail("invalid-email");
} catch (InvalidEmailException $e) {
    echo "Email error: " . $e->getMessage();
}

该代码定义了一个自定义的 InvalidEmailException 类。 validateEmail 函数为无效电子邮件抛出此异常。 自定义异常使错误处理更加具体。 它们可以包含其他方法。

多个 catch 块

此示例演示如何分别处理不同的异常类型。

multiple_catch.php
<?php

class FileNotFoundException extends Exception {}
class PermissionDeniedException extends Exception {}

function openFile($filename) {
    if (!file_exists($filename)) {
        throw new FileNotFoundException("File not found");
    }
    if (!is_readable($filename)) {
        throw new PermissionDeniedException("Permission denied");
    }
    return fopen($filename, 'r');
}

try {
    openFile("nonexistent.txt");
} catch (FileNotFoundException $e) {
    echo "File error: " . $e->getMessage();
} catch (PermissionDeniedException $e) {
    echo "Permission error: " . $e->getMessage();
} catch (Exception $e) {
    echo "General error: " . $e->getMessage();
}

代码有多个 catch 块用于不同的异常类型。 应该首先捕获更具体的异常。 最后一个 catch 块处理任何剩余的 Exception 类型。 这允许定制的错误处理。

重新抛出异常

此示例展示了如何捕获异常并重新抛出它。

rethrow.php
<?php

function processData($data) {
    if (empty($data)) {
        throw new InvalidArgumentException("Empty data");
    }
    // Process data here
}

function handleRequest($data) {
    try {
        processData($data);
    } catch (InvalidArgumentException $e) {
        error_log("Invalid data: " . $e->getMessage());
        throw $e; // Rethrow the exception
    }
}

try {
    handleRequest([]);
} catch (Exception $e) {
    echo "Request failed: " . $e->getMessage();
}

该代码捕获一个异常,记录它,然后重新抛出它。 这允许部分处理,同时让更高级别知道错误。 再次抛出相同的异常对象。 重新抛出对于日志记录很有用。

带有附加数据的异常

此示例演示了扩展 Exception 以包含额外数据。

exception_with_data.php
<?php

class ValidationException extends Exception {
    private $errors;
    
    public function __construct($message, $errors) {
        parent::__construct($message);
        $this->errors = $errors;
    }
    
    public function getErrors() {
        return $this->errors;
    }
}

function validateUser($user) {
    $errors = [];
    
    if (empty($user['name'])) {
        $errors[] = "Name is required";
    }
    if (empty($user['email'])) {
        $errors[] = "Email is required";
    }
    
    if (!empty($errors)) {
        throw new ValidationException("Validation failed", $errors);
    }
}

try {
    validateUser(['age' => 25]);
} catch (ValidationException $e) {
    echo $e->getMessage() . ": ";
    print_r($e->getErrors());
}

自定义 ValidationException 存储验证错误。 构造函数接受消息和错误详细信息。 getErrors 方法提供对附加数据的访问。 这种模式对于表单验证很有用。

Finally 块

此示例显示了始终执行的 finally 块。

finally_block.php
<?php

function processFile($filename) {
    $file = null;
    try {
        $file = fopen($filename, 'r');
        if (!$file) {
            throw new Exception("Failed to open file");
        }
        // Process file contents
    } catch (Exception $e) {
        echo "Error: " . $e->getMessage();
    } finally {
        if ($file) {
            fclose($file);
            echo "File handle closed";
        }
    }
}

processFile("example.txt");

无论是否发生异常,finally 块都会执行。 它非常适合清理代码,例如关闭文件。 无论成功与否,文件句柄都会被关闭。 finally 确保资源得到正确释放。

错误 vs 异常

此示例演示了为不可恢复的问题抛出 Error。

error_vs_exception.php
<?php

function checkMemoryLimit() {
    $memoryLimit = ini_get('memory_limit');
    $usedMemory = memory_get_usage(true);
    
    if ($usedMemory > 0.9 * $this->convertToBytes($memoryLimit)) {
        throw new Error("Memory limit exceeded");
    }
}

function convertToBytes($size) {
    // Conversion logic here
    return 0;
}

try {
    checkMemoryLimit();
} catch (Error $e) {
    echo "Fatal error: " . $e->getMessage();
    // Log and exit gracefully
}

该代码为关键问题(如内存耗尽)抛出 Error。 错误通常表明不可恢复的问题。 它们可以像异常一样被捕获。 PHP 7+ 在 Throwable 下统一了异常和错误。 谨慎使用 Error。

最佳实践

来源

PHP 异常文档

本教程介绍了 PHP 异常处理,并提供了实际示例,展示了在各种场景中使用 throw 的方法,以及 try-catch 块。

作者

我的名字是 Jan Bodnar,我是一位充满激情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出 所有 PHP 教程