Skip to content

php_ref_error

有效的错误处理对于构建健壮且易于维护的 PHP 应用程序至关重要。PHP 提供了报告脚本执行期间发生的错误的机制,以及使用 Exception(异常)来处理异常情况的更结构化的方法。

现代 PHP 开发 strongly emphasizes 使用 Exceptions(异常)来处理可恢复错误和应用程序逻辑中的异常情况,而传统的 PHP 错误 (Notices, Warnings, Fatal Errors) 通常表示与代码问题或环境设置相关的问题。

PHP 的错误报告行为由配置指令控制,这些指令通常设置在 php.ini 文件中,或通过 .htaccess,或直接在脚本中使用 ini_set() 和 error_reporting() 函数设置。

名称 默认值 描述 可修改范围 推荐设置

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)提供了一种面向对象的方式来处理错误和其他异常情况。当发生异常情况时,代码可以 throw(抛出)一个异常对象。这会中止正常的执行流程,并将控制权转移到能够处理该类型异常的最近的 catch 块。

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 仍然使用一套错误级别系统来报告通常不通过 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

函数描述
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,在生产环境中记录错误,并利用异常来实现健壮的控制流。