本文目录导读:

- 使用 set_error_handler()
- 使用 set_exception_handler()
- 同时注册错误和异常处理
- 使用 error_reporting() 控制错误级别
- 使用 register_shutdown_function()
- 最佳实践:生产环境的错误处理
在 PHP 中,错误处理注册主要涉及以下几个核心函数和机制,我将为你详细介绍最常用的几种方式。
使用 set_error_handler()
这是最常用的自定义错误处理方法,可以捕获大多数运行时错误。
<?php
// 定义错误处理函数
function customErrorHandler($errno, $errstr, $errfile, $errline) {
echo "错误级别: $errno<br>";
echo "错误信息: $errstr<br>";
echo "错误文件: $errfile<br>";
echo "错误行号: $errline<br>";
// 根据错误级别决定是否终止脚本
if ($errno === E_USER_ERROR || $errno === E_ERROR) {
die("严重错误,脚本终止");
}
// 返回 true 表示错误已被处理
return true;
}
// 注册错误处理函数
set_error_handler("customErrorHandler");
// 触发一个错误测试
echo $undefinedVar; // 未定义变量(Notice 级别)
trigger_error("自定义错误", E_USER_WARNING); // 自定义警告
?>
错误处理函数的参数:
$errno: 错误级别(如 E_WARNING, E_NOTICE 等)$errstr: 错误信息$errfile: 发生错误的文件$errline: 错误发生的行号$errcontext(可选): 错误发生时的符号表
使用 set_exception_handler()
用于处理未捕获的异常。
<?php
// 定义默认的异常处理函数
function customExceptionHandler($exception) {
echo "未捕获的异常: " . $exception->getMessage() . "<br>";
echo "在文件: " . $exception->getFile() . " 的第 " . $exception->getLine() . " 行<br>";
// 记录错误日志
error_log("异常: " . $exception->getMessage());
// 显示友好的错误页面(生产环境)
// header('Location: error.html');
}
// 设置异常处理函数
set_exception_handler("customExceptionHandler");
// 测试
throw new Exception("这是一个测试异常");
?>
同时注册错误和异常处理
更完整的错误处理方案:
<?php
// 错误处理
function handleError($errno, $errstr, $errfile, $errline) {
$message = sprintf(
"[%s] 错误: %s 在 %s 第 %d 行",
error_level_string($errno),
$errstr,
$errfile,
$errline
);
// 记录错误日志
error_log($message);
// 开发环境显示错误
if (ini_get('display_errors')) {
echo "<div style='color: red;'>$message</div>";
}
// 不要执行 PHP 内部错误处理
return true;
}
// 异常处理
function handleException($exception) {
$message = sprintf(
"异常: %s 在 %s 第 %d 行",
$exception->getMessage(),
$exception->getFile(),
$exception->getLine()
);
// 记录异常日志
error_log($message);
// 生产环境显示友好错误
if (!ini_get('display_errors')) {
echo "系统发生错误,请稍后再试";
} else {
echo "<pre>$message</pre>";
}
}
// 辅助函数:错误级别转字符串
function error_level_string($level) {
$levels = [
E_ERROR => 'E_ERROR',
E_WARNING => 'E_WARNING',
E_PARSE => 'E_PARSE',
E_NOTICE => 'E_NOTICE',
E_CORE_ERROR => 'E_CORE_ERROR',
E_CORE_WARNING => 'E_CORE_WARNING',
E_COMPILE_ERROR => 'E_COMPILE_ERROR',
E_COMPILE_WARNING => 'E_COMPILE_WARNING',
E_USER_ERROR => 'E_USER_ERROR',
E_USER_WARNING => 'E_USER_WARNING',
E_USER_NOTICE => 'E_USER_NOTICE',
E_STRICT => 'E_STRICT',
E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
E_DEPRECATED => 'E_DEPRECATED',
E_USER_DEPRECATED => 'E_USER_DEPRECATED',
];
return isset($levels[$level]) ? $levels[$level] : 'UNKNOWN';
}
// 注册错误和异常处理
set_error_handler("handleError");
set_exception_handler("handleException");
// 捕获致命错误
register_shutdown_function(function() {
$error = error_get_last();
if ($error !== NULL && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
handleError($error['type'], $error['message'], $error['file'], $error['line']);
}
});
// 测试
// echo $undefinedVar; // 触发 Notice
// trigger_error("测试错误", E_USER_WARNING); // 触发 Warning
// throw new Exception("测试异常"); // 触发异常
?>
使用 error_reporting() 控制错误级别
<?php
// 设置错误报告级别
error_reporting(E_ALL); // 报告所有错误
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED); // 报告所有错误,除了 NOTICE 和 DEPRECATED
error_reporting(0); // 关闭所有错误报告
// 配合 set_error_handler 使用
error_reporting(E_ALL);
set_error_handler(function($errno, $errstr, $errfile, $errline) {
// 只处理指定的错误级别
if (!(error_reporting() & $errno)) {
return false;
}
echo "错误: $errstr";
return true;
});
?>
使用 register_shutdown_function()
捕获致命错误(如内存耗尽、执行超时等):
<?php
function shutdownHandler() {
$error = error_get_last();
if ($error !== NULL) {
// 处理致命错误
echo "致命错误: {$error['message']}<br>";
echo "文件: {$error['file']} 行: {$error['line']}<br>";
// 记录日志
error_log("Fatal error: {$error['message']} in {$error['file']} on line {$error['line']}");
}
}
register_shutdown_function('shutdownHandler');
?>
最佳实践:生产环境的错误处理
<?php
class ErrorHandler {
public static function register() {
// 设置错误报告级别(生产环境)
error_reporting(E_ALL);
// 自定义错误处理
set_error_handler([__CLASS__, 'handleError']);
// 自定义异常处理
set_exception_handler([__CLASS__, 'handleException']);
// 捕获致命错误
register_shutdown_function([__CLASS__, 'handleShutdown']);
// 禁用错误显示
ini_set('display_errors', 0);
// 启用错误日志
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');
}
public static function handleError($errno, $errstr, $errfile, $errline) {
$message = "Error [$errno] $errstr in $errfile on line $errline";
// 记录错误日志
error_log($message);
// 根据错误级别决定是否显示错误页面
if ($errno == E_ERROR || $errno == E_USER_ERROR) {
self::displayFriendlyError();
exit;
}
return true;
}
public static function handleException($exception) {
$message = "Exception: " . $exception->getMessage() .
" in " . $exception->getFile() .
" on line " . $exception->getLine();
error_log($message);
self::displayFriendlyError();
}
public static function handleShutdown() {
$error = error_get_last();
if ($error !== null &&
in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
error_log("Fatal Error: {$error['message']} in {$error['file']} on line {$error['line']}");
self::displayFriendlyError();
}
}
private static function displayFriendlyError() {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
// 显示友好的错误页面
include 'error_page.php'; // 创建一个简单的错误页面
}
}
// 注册错误处理
ErrorHandler::register();
?>
| 函数/方法 | 用途 | 捕获范围 |
|---|---|---|
set_error_handler() |
自定义错误处理 | 大多数运行时错误(E_WARNING, E_NOTICE 等) |
set_exception_handler() |
自定义异常处理 | 未捕获的异常 |
register_shutdown_function() |
脚本关闭时执行 | 致命错误(E_ERROR 等) |
error_reporting() |
设置错误报告级别 | 控制哪些错误被报告 |
trigger_error() |
手动触发错误 | 自定义错误 |
建议在生产环境中:
- 关闭
display_errors - 开启
log_errors并指定日志文件 - 使用
set_error_handler()和set_exception_handler()统一处理 - 使用
register_shutdown_function()捕获致命错误 - 返回友好的错误页面给用户