核心函數:header()
<?php
// 必須在任何輸出前呼叫
header('Location: https://example.com/target.php');
exit; // 關鍵:阻止後續程式執行
?>
狀態碼控制
| 狀態碼 | 含義 | 適用場景 | SEO 影響 |
| 301 | Moved Permanently | 網域遷移、永久網址變更 | 傳遞權重、更新索引 |
| 302 | Found (暫時移動) | 登入後導向、A/B 測試 | 保留原網址索引 |
| 303 | See Other | POST 後導向 GET (PRG 模式) | 防止重複提交 |
| 307 | Temporary Redirect | 保持原請求方法 | API 重導向 |
| 308 | Permanent Redirect | 永久且保持方法 | REST API 遷移 |
301 永久重導向範例
<?php
header('HTTP/1.1 301 Moved Permanently');
header('Location: https://new-domain.com' . $_SERVER['REQUEST_URI']);
exit;
?>
PRG 模式(POST-Redirect-GET)
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 處理表單...
$id = saveForm($_POST);
// 303 導向結果頁,重新整理不會重複提交
header('Location: /result.php?id=' . $id, true, 303);
exit;
}
// 顯示表單
include 'form.php';
?>
動態目標重導向
<?php
// url.php?target=https://example.com
$target = $_GET['target'] ?? '/';
$allowedHosts = ['example.com', 'api.example.com'];
$parsed = parse_url($target);
if ($parsed && in_array($parsed['host'] ?? '', $allowedHosts, true)) {
header('Location: ' . $target, true, 302);
} else {
http_response_code(400);
echo '非法重導向目標';
}
exit;
?>
安全警示:開放式重導向是釣魚攻擊溫床,必須白名單驗證宿主。
輸出已啟動時的降級方案
<?php
function redirect(string $url, int $code = 302): never {
if (!headers_sent()) {
header('Location: ' . $url, true, $code);
} else {
// JavaScript 降級
echo '';
echo '';
}
exit;
}
?>
常見錯誤與除錯
Cannot modify header information → 檢查 BOM、前置空白、echo、var_dump、錯誤訊息輸出
- 使用
headers_sent($file, $line) 定位輸出源頭
- 開發環境啟用
output_buffering 或 ob_start() 容錯
測試重導向
# curl 測試
curl -I https://old.com/page.php
# HTTP/1.1 301 Moved Permanently
# Location: https://new.com/page.php
# 瀏覽器開發者工具 Network 面板查看狀態碼與 Location 標頭