PHP 通过 try/catch/finally 捕获的 exceptions 来处理错误。正确的异常处理意味着捕获特定类型、创建有意义的自定义异常、清理资源,以及不向用户暴露内部细节。
基本结构
php
<?php
try {
$data = riskyOperation();
} catch (InvalidArgumentException $e) { // catch a SPECIFIC type first
handleBadInput($e->getMessage());
} catch (DatabaseException $e) {
handleDbError($e);
} catch (Throwable $e) { // catch-all (Error OR Exception) — last
logError($e);
throw $e; // re-throw what you can't handle
} finally {
cleanup(); // ALWAYS runs (success or failure)
}
捕获 特定 的异常类型(最具体的优先),使用 Throwable 作为最终的 catch-all(覆盖 Error 和 Exception 两者),并使用 finally 进行必须始终运行的清理工作。
抛出异常和自定义异常
php
// throwing
if ($amount < 0) {
throw new InvalidArgumentException("Amount must be positive, got $amount");
}
// a custom exception for your domain
class InsufficientFundsException extends Exception {
public function __construct(private float $shortfall) {
parent::__construct("Short by $shortfall");
}
public function getShortfall(): float { return $this->shortfall; }
}
throw new InsufficientFundsException(50.0);
自定义异常类使错误处理更具表达力,让调用者能够捕获特定的领域错误。
异常链(保留原因)
php
try {
$db->query(...);
} catch (PDOException $e) {
// wrap with context, preserving the original as the "previous" exception
throw new RepositoryException("Failed to load user", 0, $e);
}
第三个构造函数参数链接原始异常($e->getPrevious()),保留了完整的根本原因以便调试。
最佳实践
text
✓ Catch SPECIFIC exceptions, not a blanket Throwable (unless intentionally last)
✓ Don't swallow exceptions silently (empty catch) — log or re-throw
✓ Use finally / proper cleanup for resources (files, connections)
✓ Create meaningful custom exceptions for domain errors
✓ SECURITY: log details internally; show users a generic message (don't leak
stack traces / internal info — display_errors off in production)
为什么这很重要
正确的异常处理对于构建强大、可靠和安全的 PHP 应用程序至关重要。
理解 try/catch/finally 结构、捕获 特定 的异常类型(用于有针对性的处理)并使用 Throwable 作为最终的 catch-all(在现代 PHP 中覆盖 Error 和 Exception 两者),以及使用 finally 进行保证的清理是日常的基础知识。
除了机制之外,最佳实践也很重要:为领域错误创建 有意义的自定义异常 使代码更具表达力,让调用者能够处理特定的失败;异常链 保留根本原因以便调试;最关键的是,不要默默吞掉异常(改为记录日志或重新抛出)防止隐藏的失败。
一个特别重要的方面是 安全性:异常和错误应该 内部记录但永远不要暴露给用户(堆栈跟踪和内部细节会泄露敏感信息并帮助攻击者——因此在生产环境中 display_errors 应该关闭)。
知道如何正确处理异常——特定的捕获、自定义异常、清理、异常链以及安全的日志记录而非暴露——将健壮的专业 PHP 代码与容易崩溃或泄露信息的脆弱代码区分开来,使其成为构建可靠、安全应用程序的重要知识。
