PHP 實現跳轉主要有三種機制:HTTP Header(服務端)、Meta Refresh(瀏覽器解析)、JavaScript(客戶端執行)。本文對比適用場景、參數細節、常見坑點與最佳實踐封裝。
function redirect(string $url, int $code = 302): void {
// 確保無輸出
if (headers_sent($file, $line)) {
trigger_error("Headers already sent in $file:$line", E_USER_WARNING);
// 降級 JS 跳轉
echo "";
exit;
}
http_response_code($code);
header("Location: $url", true, $code);
exit; // 關鍵:阻止後續代碼執行
}
// 使用
redirect('/login.php', 302); // 臨時跳轉
redirect('/new-url', 301); // 永久跳轉 (SEO)
redirect('https://example.com'); // 跨域
header() 前絕對不能有任何輸出(含空白、BOM、echo);Location: 後無空格,header('Location:...') 大小寫不敏感;header() 後代碼仍會執行,必須 exit。function meta_redirect(string $url, int $delay = 0): void {
$url = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
echo "";
// 可選:顯示倒計時頁面
if ($delay > 0) {
echo "{$delay} 秒後自動跳轉... 立即跳轉
";
}
}
// 使用
meta_redirect('/dashboard.php', 3); // 3 秒後跳轉
function js_redirect(string $url, bool $replace = false): void {
$url = addslashes($url);
$method = $replace ? 'replace' : 'href';
echo "";
exit;
}
// 使用
js_redirect('/app.php'); // 記錄歷史
js_redirect('/app.php', true); // replace:不記錄歷史,返回鍵不回跳轉頁
| 維度 | Header | Meta | JavaScript |
|---|---|---|---|
| 執行階段 | 服務端響應頭 | 瀏覽器解析 HTML | 客戶端 JS 引擎 |
| SEO | ✅ 301/302 傳遞權重 | ❌ 不傳遞 | ❌ 不傳遞 |
| 延遲跳轉 | ❌ 需配合 sleep/緩衝 | ✅ content="N;url=" | ✅ setTimeout |
| 輸出前置條件 | 嚴格:無任何輸出 | 寬鬆:任意位置 | 寬鬆:任意位置 |
| 跨域 | ✅ | ✅ | ✅ |
| 攜帶狀態碼 | ✅ | ❌ | ❌ |
| 歷史記錄控制 | ❌ | ❌ | ✅ replace/href |
class Redirect {
public static function to(string $url, int $code = 302): never {
if (!headers_sent()) {
http_response_code($code);
header("Location: $url", true, $code);
} else {
// 輸出已開始,降級
self::js($url, true);
}
exit;
}
public static function js(string $url, bool $replace = false): never {
$url = addslashes($url);
$method = $replace ? 'replace' : 'href';
echo "";
exit;
}
public static function meta(string $url, int $delay = 0, string $msg = ''): never {
$url = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
echo "";
if ($delay && $msg) echo "$msg 立即跳轉
";
exit;
}
// AJAX 統一返回
public static function ajax(string $url, string $msg = '操作成功'): never {
header('Content-Type: application/json');
echo json_encode(['success' => true, 'message' => $msg, 'redirect' => $url]);
exit;
}
}
// 使用
Redirect::to('/login.php');
Redirect::ajax('/dashboard', '登入成功');
?> 後無換行,或全文件省略 ?>;Location: ./page.php 可能在某些代理下異常,建議絕對路徑 /page.php 或完整 URL;urlencode。 根據場景選擇正確跳轉方式,並封裝統一類,能消除 90% 的跳轉相關 Bug。