引言:为什么错误处理是可靠 PHP 代码的基石
每位 PHP 开发者都会遇到错误。无论是无效的用户输入、数据库不可用,还是意外的 API 故障——如果没有适当的错误处理,应用程序就会变成一个脆弱的结构,随时可能“崩溃”。PHP 中的错误处理不仅仅是为了避免白屏死机(WSOD),更是创建稳定、安全且可维护 Web 应用程序的基本原则。
在本文中,我们将深入解析 PHP 错误处理的各个方面:从基础的 try/catch 机制,到创建自定义异常以及高级日志策略。您将学习如何将混乱的错误转化为可控且可预测的流程。
基础知识:try、catch、finally 和 throw
try/catch 块 —— 第一道防线
PHP 的异常机制基于 try/catch 结构。可能引发错误的代码被放置在 try 块内。如果其中发生异常,执行会立即跳转到 catch 块,在那里对错误进行处理。
<?phptry { $file = fopen('important_data.txt', 'r'); if (!$file) { throw new Exception('Failed to open file'); } // Work with the file fclose($file);} catch (Exception $e) { echo 'Error: ' . $e->getMessage();}?>重要的是要理解:PHP 中并非所有错误都是异常。标准的警告和通知并不会自动生成异常。要捕获它们,需要进行特殊配置(请参见“高级技术”部分)。
finally 块 —— 保证执行
finally 块始终会执行,无论是否抛出异常。这是释放资源的理想位置:关闭文件、数据库连接或释放内存。
<?phpfunction processData($data) { $connection = null; try { $connection = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); // Execute queries return $connection->query($data); } catch (PDOException $e) { // Log the error error_log('DB Error: ' . $e->getMessage()); return false; } finally { // Close the connection in any case if ($connection) { $connection = null; } }}?>throw 语句 —— 创建自己的异常
使用 throw,您可以在代码的任何位置生成异常。这使得您可以创建清晰且可预测的错误场景。
<?phpfunction validateAge($age) { if (!is_numeric($age)) { throw new InvalidArgumentException('Age must be a number'); } if ($age < 0 || $age > 150) { throw new OutOfRangeException('Age is outside the valid range'); } return true;}
try { validateAge('abc');} catch (InvalidArgumentException $e) { echo 'Validation error: ' . $e->getMessage();} catch (OutOfRangeException $e) { echo 'Invalid range: ' . $e->getMessage();}?>自定义异常类
标准的异常类(Exception、RuntimeException、InvalidArgumentException)涵盖了许多场景,但对于复杂项目,最好创建自己的异常层次结构。这可以提高代码的可读性并简化调试。
创建自定义异常类
<?phpclass DatabaseException extends Exception { private $queryString; public function __construct($message, $query = '', $code = 0, Throwable $previous = null) { $this->queryString = $query; parent::__construct($m