php_ref_error
PHP 错误和异常处理
Section titled “PHP 错误和异常处理”错误处理介绍
Section titled “错误处理介绍”有效的错误处理对于构建健壮且易于维护的 PHP 应用程序至关重要。PHP 提供了报告脚本执行期间发生的错误的机制,以及使用 Exception(异常)来处理异常情况的更结构化的方法。
现代 PHP 开发 strongly emphasizes 使用 Exceptions(异常)来处理可恢复错误和应用程序逻辑中的异常情况,而传统的 PHP 错误 (Notices, Warnings, Fatal Errors) 通常表示与代码问题或环境设置相关的问题。
错误报告配置
Section titled “错误报告配置”PHP 的错误报告行为由配置指令控制,这些指令通常设置在 php.ini 文件中,或通过 .htaccess,或直接在脚本中使用 ini_set() 和 error_reporting() 函数设置。
关键配置指令:
Section titled “关键配置指令:”名称 默认值 描述 可修改范围 推荐设置
error_reporting
E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED (较旧的 PHP 版本)
E_ALL (现代 PHP 版本)
设置错误报告级别。使用预定义常量(见下文)。控制报告哪些类型的错误。
PHP_INI_ALL
开发环境: E_ALL
生产环境: E_ALL(但要记录错误,不要显示)
display_errors
"1" (在生产环境中通常会被覆盖为 "0")
指定是否将错误直接输出到浏览器/控制台。
PHP_INI_ALL
开发环境: "1"
生产环境: "0" (存在安全风险!)
display_startup_errors
"0"
控制是否显示 PHP 启动序列期间(在脚本执行开始之前)发生的错误。除非调试启动问题,否则请保持关闭。
PHP_INI_ALL
开发环境: "0" (或 "1" 用于调试)
生产环境: "0"
log_errors
"0"
定义是否应该记录错误消息。
PHP_INI_ALL
开发/生产环境: "1"
error_log
平台特定(例如,Apache 错误日志,syslog)
指定在启用 log_errors 时应将错误记录到哪个文件或系统日志记录器中。
PHP_INI_ALL
开发/生产环境: 设置为可写的文件路径(例如,/var/log/php_errors.log)或 syslog。
log_errors_max_len
"1024"
设置记录的错误消息的最大长度(以字节为单位)。0 表示没有限制。
PHP_INI_ALL
通常保持默认值或在需要时增加。
ignore_repeated_errors
"0"
如果为 "1",则忽略来自相同文件/行的日志中的重复消息。
PHP_INI_ALL
除非日志噪音过大,否则保持 "0"。
ignore_repeated_source
"0"
如果为 "1",则忽略重复消息,无论来源文件/行如何。
PHP_INI_ALL
通常保持 "0"。
html_errors
"1"
如果为 "1",则在 display_errors 开启时,使用 HTML 标签格式化错误消息。
PHP_INI_ALL
如果 display_errors 关闭(生产环境),则无关紧要。
最佳实践:
- 开发环境: 设置
error_reporting(E_ALL);和ini_set('display_errors', 1);以立即查看所有问题。 - 生产环境: 设置
error_reporting(E_ALL);,ini_set('display_errors', 0);,ini_set('log_errors', 1);,并配置error_log将错误写入安全的文件或 syslog。绝不要在生产环境中直接向用户显示错误,因为这可能会泄露敏感信息。
异常(Exceptions)
Section titled “异常(Exceptions)”异常(Exceptions)提供了一种面向对象的方式来处理错误和其他异常情况。当发生异常情况时,代码可以 throw(抛出)一个异常对象。这会中止正常的执行流程,并将控制权转移到能够处理该类型异常的最近的 catch 块。
基本语法 (try...catch...finally):
Section titled “基本语法 (try...catch...finally):”try { // 可能抛出异常的代码 $result = potentiallyRiskyOperation(); if ($result === false) { throw new Exception("Operation failed!"); } echo "Operation successful.";
} catch (SpecificExceptionType $e) { // 处理特定类型的异常 echo "Caught SpecificException: " . $e->getMessage(); // 记录错误,提供用户反馈等
} catch (Exception $e) { // 捕获任何一般的 Exception (或 Throwable) // 处理其他异常 echo "Caught generic Exception: " . $e->getMessage() . "<br>"; echo "File: " . $e->getFile() . " Line: " . $e->getLine() . "<br>"; // echo "Trace: <pre>" . $e->getTraceAsString() . "</pre>"; // 用于调试
} finally { // 可选块:此处的代码在 try/catch 块之后 *总是* 执行, // 无论是否抛出或捕获了异常。 // 用于清理资源(例如,关闭文件或数据库连接)。 echo "<br>Executing finally block.";}PHP 7+ 引入了 Throwable 接口,Exception 和 Error 都实现了该接口。你可以捕获 Throwable 来处理几乎所有情况,但通常捕获更具体的异常类型更好。
传统 PHP 错误
Section titled “传统 PHP 错误”PHP 仍然使用一套错误级别系统来报告通常不通过 try...catch 处理的问题(除非自定义错误处理器将其转换为异常)。
错误级别常量 (用于 error_reporting()):
Section titled “错误级别常量 (用于 error_reporting()):”常量 描述 类型
E_ERROR
致命的运行时错误。脚本执行停止。
Fatal Error
E_WARNING
运行时警告(非致命)。脚本执行继续。
Warning
E_PARSE
编译时解析错误。由解析器生成,脚本不会运行。
Parse Error
E_NOTICE
运行时通知。指示潜在问题,但脚本继续(例如,使用未定义变量)。
Notice
E_CORE_ERROR
PHP 初始化启动期间的致命错误。
Fatal Error
E_CORE_WARNING
PHP 初始化启动期间的警告。
Warning
E_COMPILE_ERROR
Zend Engine 生成的致命编译时错误。
Fatal Error
E_COMPILE_WARNING
编译时警告(非致命)。
Warning
E_USER_ERROR
用户生成的致命错误消息(通过 trigger_error())。脚本停止。
User Error
E_USER_WARNING
用户生成的警告消息(通过 trigger_error())。脚本继续。
User Warning
E_USER_NOTICE
用户生成的通知消息(通过 trigger_error())。脚本继续。
User Notice
E_STRICT
建议进行更改以提高代码兼容性/互操作性(自 PHP 5.4 起包含在 E_ALL 中)。
Strict Standards
E_RECOVERABLE_ERROR
可捕获的致命错误(例如,类型提示不匹配)。可由错误处理器捕获。
Catchable Fatal Error
E_DEPRECATED
关于在未来 PHP 版本中将被移除的代码的运行时通知。
Deprecated
E_USER_DEPRECATED
用户生成的废弃消息(通过 trigger_error())。
User Deprecated
E_ALL
所有错误和警告常量的组合(PHP 5.4 之前不包含 E_STRICT)。推荐用于开发环境。
All Errors/Warnings
关键错误处理函数
Section titled “关键错误处理函数”| 函数 | 描述 |
|---|---|
error_reporting(?int $level = null) | 设置或获取当前的错误报告级别。 |
ini_set(string $option, string|int|bool|null $value) | 设置配置选项(如 ‘display_errors’)的值。 |
trigger_error(string $message, int $error_level = E_USER_NOTICE) | 生成用户级别的错误/警告/通知。对于自定义库的错误很有用。 |
set_error_handler(?callable $callback, int $error_levels = E_ALL) | 设置一个自定义函数来处理 PHP 错误。可用于将错误转换为异常。 |
restore_error_handler() | 恢复之前的错误处理函数。 |
set_exception_handler(?callable $callback) | 设置一个默认函数来处理未捕获的异常。 |
restore_exception_handler() | 恢复之前的异常处理函数。 |
error_get_last() | 返回一个描述最后发生的错误(如果有)的关联数组。 |
error_log(string $message, int $message_type = 0, ?string $destination = null, ?string $additional_headers = null) | 将错误消息发送到配置的日志、电子邮件地址或特定文件。 |
debug_backtrace(int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT, int $limit = 0) | 生成 PHP 回溯(backtrace),显示函数调用堆栈。 |
debug_print_backtrace(int $options = 0, int $limit = 0) | 直接打印 PHP 回溯(backtrace)。 |
示例:将错误转换为异常的自定义错误处理器
Section titled “示例:将错误转换为异常的自定义错误处理器”<?php// 设置最高的错误报告级别error_reporting(E_ALL);
// 自定义错误处理器函数set_error_handler(function ($severity, $message, $file, $line) { // 遵循 error_reporting 设置的级别 if (!(error_reporting() & $severity)) { return false; // 对于此严重级别的错误,错误报告已关闭 } // 为 PHP 错误抛出 ErrorException throw new ErrorException($message, 0, $severity, $file, $line);});
try { echo $undefinedVariable; // 这将触发一个 Notice 错误,现在被转换为 ErrorException
// 触发用户警告的示例 trigger_error("This is a custom warning", E_USER_WARNING);
} catch (ErrorException $e) { echo "Caught ErrorException (from PHP error):<br>"; echo "Severity: " . $e->getSeverity() . "<br>"; echo "Message: " . htmlspecialchars($e->getMessage()) . "<br>"; echo "File: " . htmlspecialchars($e->getFile()) . " Line: " . $e->getLine() . "<br>"; // 在实际应用中在此处记录错误} catch (Exception $e) { echo "Caught generic Exception: " . htmlspecialchars($e->getMessage());}
// 恢复默认的错误处理器(可选)// restore_error_handler();
echo "<br>捕获错误后脚本继续执行。";
?>有效的错误和异常处理是稳定应用程序的关键。在开发环境中使用 E_ALL,在生产环境中记录错误,并利用异常来实现健壮的控制流。