Web 開發中頁面跳轉是高頻需求:登入後導向、表單提交跳轉、錯誤頁面引導。PHP 作為服務端語言,配合 HTTP 協議與前端技術,提供了多種跳轉方式。本文系統對比三大主流方案,給出生產環境選型建議。
<?php
// 1. 立即跳轉 (302 Found)
header('Location: /user/dashboard');
exit; // 關鍵:阻止後續代碼執行
// 2. 延遲跳轉 (Refresh Header,非標準但廣泛支援)
$seconds = 3;
$url = '/payment/success';
header("Refresh: {$seconds}; url={$url}");
echo "{$seconds} 秒後自動跳轉至訂單頁...";
// 後續代碼仍會執行,除非 exit
exit 或 die,否則腳本繼續執行可能導致邏輯錯誤或資源浪費。<?php
$url = 'https://example.com';
echo "<meta http-equiv='Refresh' content='3;url={$url}'>";
echo "3 秒後跳轉... <a href='{$url}'>點此手動跳轉</a>";
<?php
$url = '/user/profile';
$msg = '登入成功,正在跳轉...';
// 方案 A: 彈窗提示 + 跳轉 (阻塞式,體驗差,不推薦)
echo "<script>alert('{$msg}'); window.location.href='{$url}';</script>";
// 方案 B: 直接跳轉 (推薦)
echo "<script>window.location.href='{$url}';</script>";
// 方案 C: 延遲跳轉 + 倒計時顯示 (最佳體驗)
echo "<script>
var sec = 3;
var timer = setInterval(function() {
document.getElementById('countdown').innerText = sec--;
if (sec < 0) { clearInterval(timer); window.location.href = '{$url}'; }
}, 1000);
</script>";
echo "{$msg} <span id='countdown'>3</span> 秒後跳轉...";
| 場景 | 首選方案 | 備選 | 關鍵點 |
|---|---|---|---|
| 登入/註冊/表單提交成功 | Header Location (302) | JS 延遲跳轉 | 語義正確、防重複提交、SEO 友好 |
| 權限不足/404/錯誤頁引導 | Header Location (302/403/404) | Meta Refresh | 正確狀態碼、無輸出限制用 Meta |
| 需倒計時提示/廣告頁/支付結果頁 | JS 倒計時 + location.href | Meta Refresh | 豐富交互、可取消、可統計停留時長 |
| 已輸出內容後才決定跳轉 | JS / Meta Refresh | — | Header 已失效 |
| API 介面/異步請求 | 返回 JSON {redirect_url} | — | 前端路由控制 |
<?php
/**
* 統一跳轉函數
* @param string $url 目標 URL
* @param int $delay 延遲秒數 (0 為立即 Header 跳轉)
* @param string $msg 提示訊息 (僅延遲模式生效)
* @param int $status HTTP 狀態碼 (301/302/303)
*/
function redirect($url, $delay = 0, $msg = '', $status = 302) {
// 參數驗證
if (empty($url)) return false;
// 立即跳轉模式
if ($delay === 0) {
// 若已有輸出,強制用 JS 降級
if (headers_sent()) {
echo "<script>window.location.replace('" . addslashes($url) . "');</script>";
exit;
}
header("Location: {$url}", true, $status);
exit;
}
// 延遲跳轉模式 (JS 方案,體驗最佳)
$msg = $msg ?: "{$delay} 秒後自動跳轉...";
$jsUrl = addslashes($url);
echo "<!DOCTYPE html><html><head><meta charset='UTF-8'><title>跳轉中...</title>";
echo "<style>body{font-family:sans-serif;text-align:center;padding:50px;} .btn{display:inline-block;margin-top:20px;padding:10px 20px;background:#007bff;color:#fff;text-decoration:none;border-radius:4px;}</style>";
echo "</head><body>";
echo "<p>{$msg} <span id='cd'>{$delay}</span> 秒</p>";
echo "<a href='{$url}' class='btn'>立即跳轉</a>";
echo "<script>
var s = {$delay};
var el = document.getElementById('cd');
var t = setInterval(function() {
el.textContent = --s;
if (s <= 0) { clearInterval(t); window.location.replace('{$jsUrl}'); }
}, 1000);
</script>";
echo "</body></html>";
exit;
}
// 使用示例
// redirect('/dashboard'); // 立即
// redirect('/pay/success', 3, '支付成功'); // 3秒倒計時
核心原則: 能用 Header Location 絕不選 JS;需倒計時/提示用 JS 方案;已輸出內容強制降級 JS。統一封裝減少維護成本。