本文目录导读:

- 使用 set_error_handler() 自定义错误处理函数(推荐)
- 使用 try-catch 处理异常(推荐面向对象方式)
- 使用 Apache 的 .htaccess 配置
- 使用 Nginx 配置
- 完整的错误处理封装示例
- 错误页面示例(404.php)
- 最佳实践建议
在 PHP 中自定义错误页面,主要有以下几种方式,按推荐程度和场景排序:
使用 set_error_handler() 自定义错误处理函数(推荐)
<?php
// 设置自定义错误处理函数
set_error_handler(function($errno, $errstr, $errfile, $errline) {
// 记录错误日志
error_log("错误: [$errno] $errstr in $errfile on line $errline");
// 显示自定义错误页面
if (ini_get('display_errors')) {
// 开发环境:显示详细信息
echo "<div style='border:1px solid red; padding:20px; margin:20px;'>";
echo "<h2>系统错误</h2>";
echo "<p>错误编号: $errno</p>";
echo "<p>错误信息: $errstr</p>";
echo "<p>文件: $errfile 第 $errline 行</p>";
echo "</div>";
} else {
// 生产环境:显示友好错误页面
include 'error_pages/generic_error.php';
}
return true;
});
// 恢复之前定义的错误处理
// restore_error_handler();
?>
使用 try-catch 处理异常(推荐面向对象方式)
<?php
// 设置全局异常处理
set_exception_handler(function($exception) {
// 记录异常
error_log("未捕获异常: " . $exception->getMessage());
// 显示自定义错误页面
http_response_code(500);
require 'error_pages/500.html';
});
// 在代码中使用 try-catch
try {
// 可能出错的代码
$result = 10 / 0;
} catch (DivisionByZeroError $e) {
// 显示自定义错误
http_response_code(400);
include 'error_pages/400_bad_request.php';
exit;
} catch (Exception $e) {
// 通用错误处理
http_response_code(500);
include 'error_pages/500.php';
exit;
}
?>
使用 Apache 的 .htaccess 配置
# 在网站根目录的 .htaccess 文件中添加 ErrorDocument 400 /error_pages/400.php ErrorDocument 401 /error_pages/401.php ErrorDocument 403 /error_pages/403.php ErrorDocument 404 /error_pages/404.php ErrorDocument 500 /error_pages/500.php
使用 Nginx 配置
# 在 nginx 配置中添加
error_page 404 /error_pages/404.html;
error_page 500 502 503 504 /error_pages/50x.html;
location = /error_pages/404.html {
root /var/www/html;
internal;
}
location = /error_pages/50x.html {
root /var/www/html;
internal;
}
完整的错误处理封装示例
<?php
class ErrorHandler {
public function __construct() {
// 设置错误和异常处理
set_error_handler([$this, 'handleError']);
set_exception_handler([$this, 'handleException']);
// 关闭 PHP 显示错误
ini_set('display_errors', 0);
ini_set('log_errors', 1);
}
public function handleError($errno, $errstr, $errfile, $errline) {
// 根据错误类型设置对应的 HTTP 状态码
$statusCode = 500;
switch ($errno) {
case E_USER_WARNING:
case E_WARNING:
$statusCode = 400;
break;
case E_USER_NOTICE:
case E_NOTICE:
$statusCode = 200;
break;
default:
$statusCode = 500;
}
// 记录错误
$this->logError($errno, $errstr, $errfile, $errline);
// 显示错误页面
$this->displayErrorPage($statusCode, [
'message' => $errstr,
'file' => $errfile,
'line' => $errline
]);
return true;
}
public function handleException($exception) {
$statusCode = $exception->getCode() ?: 500;
$this->logError(
get_class($exception),
$exception->getMessage(),
$exception->getFile(),
$exception->getLine()
);
$this->displayErrorPage($statusCode, [
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
'line' => $exception->getLine()
]);
}
private function logError($type, $message, $file, $line) {
$logMessage = date('Y-m-d H:i:s') . " [$type] $message in $file:$line" . PHP_EOL;
error_log($logMessage, 3, __DIR__ . '/logs/error.log');
}
private function displayErrorPage($statusCode, $errorInfo) {
http_response_code($statusCode);
// 根据状态码选择不同的错误页面
$errorPage = __DIR__ . '/error_pages/' . $statusCode . '.php';
if (file_exists($errorPage)) {
extract($errorInfo);
include $errorPage;
} else {
// 默认错误页面
echo "<h1>错误 {$statusCode}</h1>";
echo "<p>{$errorInfo['message']}</p>";
}
exit;
}
}
// 使用
$errorHandler = new ErrorHandler();
?>
错误页面示例(404.php)
<?php
// pages/errors/404.php
$title = "404 - 页面未找到";
?>
<!DOCTYPE html>
<html>
<head><?php echo $title; ?></title>
<style>
.error-container {
text-align: center;
padding: 50px;
max-width: 600px;
margin: 0 auto;
}
.error-code {
font-size: 120px;
color: #e74c3c;
margin: 0;
}
.error-message {
font-size: 24px;
color: #333;
}
.back-home {
display: inline-block;
margin-top: 20px;
padding: 10px 20px;
background: #3498db;
color: white;
text-decoration: none;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="error-container">
<h1 class="error-code">404</h1>
<p class="error-message">抱歉,您请求的页面不存在</p>
<p>可能的原因:</p>
<ul>
<li>链接已经失效</li>
<li>页面已被删除</li>
<li>输入的网址有误</li>
</ul>
<a href="/" class="back-home">返回首页</a>
</div>
</body>
</html>
最佳实践建议
- 开发环境:显示详细错误信息
- 生产环境:隐藏敏感信息,显示友好错误页面
- 日志记录:始终记录错误详情
- 分级处理:根据错误类型显示不同的错误页面
- 框架使用:如果使用框架(Laravel、Symfony等),通常有内置的错误处理机制
选择哪种方式取决于你的应用架构和需求,推荐组合使用 set_error_handler() 和 try-catch 来实现完整的错误处理。