專業的 404 頁面不僅要告知用戶「頁面不存在」,更應記錄訪問詳情、輔助 SEO 診斷、可選發送管理員郵件。本文提供一個可配置、可擴展的 PHP 404 處理器實現。
<?php
// 404.php - 放置於網站根目錄,Apache/Nginx 配置 ErrorDocument 404 /404.php
$config = [
'domain' => 'example.com', // 無 www
'docroot' => 'https://example.com', // 無尾部斜杠
'font' => 'system-ui, sans-serif',
'fontSize' => '1rem',
'bgColor' => '#ffffff',
'textColor' => '#1a1a1a',
'reportLevel' => 2, // 0/1/2
'adminEmail' => 'webmaster@example.com',
];
$uri = $_SERVER['REQUEST_URI'] ?? '/';
$referer = $_SERVER['HTTP_REFERER'] ?? '直接訪問/書籤';
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$time = gmdate('Y-m-d H:i:s') . ' GMT';
// 1. 輸出友好頁面
http_response_code(404);
header('Content-Type: text/html; charset=utf-8');
echo <<<HTML
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="utf-8">
<title>404 - 頁面未找到</title>
<style>
body{font-family:{$config['font']};font-size:{$config['fontSize']};background:{$config['bgColor']};color:{$config['textColor']};display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;padding:2rem;text-align:center;}
h1{font-size:6rem;margin:0 0 1rem;font-weight:700;color:#e53e3e;}
p{max-width:40rem;line-height:1.6;}
.detail{font-family:monospace;font-size:0.875rem;color:#718096;word-break:break-all;}
</style>
</head>
<body>
<h1>404</h1>
<p>抱歉,您訪問的頁面不存在或已移除。</p>
<p class="detail">請求路徑:{$config['docroot']}{$uri}</p>
<p><a href="{$config['docroot']}" style="color:#3182ce;text-decoration:underline;">返回首頁</a></p>
</body>
</html>
HTML;
// 2. 郵件上報
if ($config['reportLevel'] !== 0) {
$shouldReport = ($config['reportLevel'] === 2) ||
($config['reportLevel'] === 1 && stripos($referer, $config['domain']) !== false);
if ($shouldReport) {
$subject = "【404 報告】{$config['domain']} - {$uri}";
$body = "時間:{$time}\nIP:{$ip}\n請求:{$config['docroot']}{$uri}\n來源:{$referer}\nUA:{$_SERVER['HTTP_USER_AGENT'] ?? 'unknown'}";
@mail($config['adminEmail'], $subject, $body, "From: {$config['adminEmail']}");
}
}
exit;
?>
# Apache (.htaccess 或虛擬主機)
ErrorDocument 404 /404.php
# Nginx
error_page 404 /404.php;
location = /404.php {
internal; # 禁止直接訪問
fastcgi_pass php-fpm;
include fastcgi_params;
fastcgi_param REQUEST_URI $request_uri; # 確保傳遞原始 URI
}
/var/log/nginx/404.log),接入 ELK/Loki 分析趨勢。REQUEST_URI 匹配站點地圖,推薦相似路徑(Levenshtein 距離)。INCR 404:ip:{$ip} EX 60 超過閾值返回 429。Accept-Language 輸出對應語言頁面。