| 狀態碼 | 含義 | SEO 影響 | 適用場景 |
|---|---|---|---|
| 301 | Moved Permanently (永久移動) | 權重傳遞,搜索引擎更新索引 | 域名遷移、HTTPS 強制、URL 結構永久變更 |
| 302 | Found (臨時移動) | 權重不傳遞,保留原 URL 索引 | 臨時維護、A/B 測試、登錄跳轉 |
<?php
// 必須在任何輸出之前
header("HTTP/1.1 301 Moved Permanently");
header("Location: https://www.example.com/new-page");
exit; // 關鍵:防止後續代碼執行
?>
<?php
$targetUrl = 'https://www.example.com/new-page';
header("Location: {$targetUrl}", true, 301);
exit;
<?php
$targetHost = 'example.com'; // 目標主域
$requestUri = $_SERVER['REQUEST_URI'] ?? '';
if (isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] !== $targetHost) {
// 構建目標 URL (保持協議、路徑、查詢參數)
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$targetUrl = "{$scheme}://{$targetHost}{$requestUri}";
header("HTTP/1.1 301 Moved Permanently");
header("Location: {$targetUrl}");
exit;
}
// 正常業務邏輯...
?>
原因:在 header() 前有任何輸出 (echo、空白字符、BOM、錯誤信息)。
解決:
為文件第一行第一字符,前無空行空格。ob_start() 在文件頂部 (但不推薦掩蓋架構問題)。// 錯誤:冒號後有空格
header("Location: https://example.com"); // 部分客戶端可能失敗
// 正確:冒號後直接跟 URL
header("Location:https://example.com"); // 或 header("Location: https://example.com"); (RFC 7231 允許空格,但最保險無空格)
header() 只發送頭部,**不會終止腳本執行**。後續代碼仍會運行,可能導致邏輯錯誤或輸出干擾。
header("Location: /new-url", true, 301);
exit; // 必須
RFC 7231 要求 Location 為絕對 URI。雖然現代瀏覽器兼容相對路徑,但**強烈建議使用完整 URL** (含協議、域名)。
PHP 層面重定向需啟動 PHP 進程,高併發下有開銷。建議在 Web 服務器層完成:
server {
server_name www.example.com;
return 301 https://example.com$request_uri;
}
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
# curl 檢查 curl -I https://www.example.com/old-page # 應返回: # HTTP/1.1 301 Moved Permanently # Location: https://example.com/old-page # Content-Type: text/html; charset=UTF-8
header("Location: ...", true, 301) 或分兩行發送狀態行+Location。exit;。curl -I 驗證狀態碼與 Location。