首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 實現 301 永久重定向:正確姿勢與常見坑點

     編輯:PHP 相關知識

301 vs 302:核心區別

狀態碼含義SEO 影響適用場景
301Moved Permanently (永久移動)權重傳遞,搜索引擎更新索引域名遷移、HTTPS 強制、URL 結構永久變更
302Found (臨時移動)權重不傳遞,保留原 URL 索引臨時維護、A/B 測試、登錄跳轉

PHP 實現 301 的三種正確寫法

寫法 1:分離發送狀態行與 Location (最兼容)

<?php
// 必須在任何輸出之前
header("HTTP/1.1 301 Moved Permanently");
header("Location: https://www.example.com/new-page");
exit; // 關鍵:防止後續代碼執行
?>

寫法 2:header() 第三參數直接指定狀態碼 (PHP 4.3+)

<?php
$targetUrl = 'https://www.example.com/new-page';
header("Location: {$targetUrl}", true, 301);
exit;

寫法 3:配合 $_SERVER 實現全站規范化跳轉 (如 www → non-www)

<?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;
}
// 正常業務邏輯...
?>

常見錯誤與解決方案

1. "Cannot modify header information - headers already sent"

原因:在 header() 前有任何輸出 (echo、空白字符、BOM、錯誤信息)。

解決:

  • 文件保存為 UTF-8 無 BOM 編碼 (編輯器設置)。
  • 確保 為文件第一行第一字符,前無空行空格。
  • 重定向邏輯放在模板輸出/HTML 之前。
  • 開啟輸出緩衝:ob_start() 在文件頂部 (但不推薦掩蓋架構問題)。

2. Location 值格式錯誤

// 錯誤:冒號後有空格
header("Location: https://example.com"); // 部分客戶端可能失敗

// 正確:冒號後直接跟 URL
header("Location:https://example.com"); // 或 header("Location: https://example.com"); (RFC 7231 允許空格,但最保險無空格)

3. 忘記 exit/die

header() 只發送頭部,**不會終止腳本執行**。後續代碼仍會運行,可能導致邏輯錯誤或輸出干擾。

header("Location: /new-url", true, 301);
exit; // 必須

4. 相對路徑 vs 絕對 URL

RFC 7231 要求 Location 為絕對 URI。雖然現代瀏覽器兼容相對路徑,但**強烈建議使用完整 URL** (含協議、域名)。

進階:Nginx/Apache 層面實現 301 (性能更優)

PHP 層面重定向需啟動 PHP 進程,高併發下有開銷。建議在 Web 服務器層完成:

Nginx

server {
    server_name www.example.com;
    return 301 https://example.com$request_uri;
}

Apache (.htaccess)

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。
  • [ ] 重定向代碼放在**所有輸出之前**。
  • [ ] 文件編碼 **UTF-8 無 BOM**。
  • [ ] 緊跟 exit;。
  • [ ] Location 使用**絕對 URL**。
  • [ ] 高流量場景遷移至 Nginx/Apache 配置。
  • [ ] 使用 curl -I 驗證狀態碼與 Location。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved