
我有一個 WordPress 網站。我想將 .php 網址重新導向到不含 .php 字尾的網址。 .htaccess 如下:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)\.php$ "$1" [R=301,L,NC]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
但當我訪問時https://www.example.com/somepage.php,頁面無法顯示。瀏覽器中顯示以下錯誤:
The page isn’t redirecting properly
An error occurred during a connection to www.example.com.
This problem can sometimes be caused by disabling or refusing to accept cookies.
網址列中的 url 變成 https://www.example.com/index。
如果我將重寫規則更改為:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)\.html$ "$1" [R=301,L,NC]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
並參觀https://www.example.com/somepage.html,它已成功重定向到https://www.example.com/somepage且網頁顯示正常。為什麼?
答案1
因為,由於重定向是無條件的,你最終會再次重定向後URL 已重寫為index.php
(WordPress 前端控制器)。
當您請求時/somepage.php
:
- 您將被重新導向到
/somepage
(根據第一條規則)。重定向回應被傳送回客戶端。 - 在第二個請求時,由最後一條規則
/somepage
在內部重寫。/index.php
然後重寫引擎重新啟動(在目錄情境)... /index.php
被重定向到/index
(根據第一條規則)。重定向回應被傳送回客戶端。- 在第三個請求上,由最後一次重寫
/index
在內部重寫。/index.php
然後重寫引擎重新啟動..... - 轉到 3(陷入無限重定向循環)。
在一個目錄上下文(如.htaccess
)重寫引擎並不簡單地透過腳本進行單次傳遞。它會循環直到 URL 不變地通過。 (除非您END
在 Apache 2.4 上使用該標誌,否則會發生外部 3xx 重定向。)
變更為刪除.html
工作正常,因為您正在重寫/index.php
,它不以 結尾.html
,因此重定向指令(刪除.html
)不符。
要解決此問題,您需要避免重定向重寫的請求。您可以透過以下任一方式執行此操作:
END
在最後一次重寫時使用標誌(Apache 2.4+),而不是L
防止重寫引擎的任何進一步循環。儘管您應該避免更改預設的 WordPress 指令(請參閱下文),因此這可能不是首選選項。這在 Apache 2.2 上也不起作用。或者,檢查伺服器變數
.php
的副檔名THE_REQUEST
(其中包含 HTTP 請求標頭的初始行,並且在重寫請求時不會變更)。例如:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{THE_REQUEST} [A-Z]{3,7}\s/[^?]+\.php(?:\?|\s|$) [NC] RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
或者,檢查
REDIRECT_STATUS
環境變量,該變量在初始請求時為空,並在第一次成功重寫時設置為 200(如 200 OK HTTP 狀態)(這比上面更複雜的正則表達式更簡單)。例如:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
但是,您不應該編輯該部分內的程式碼# BEGIN WordPress
,因為 WordPress 本身會嘗試維護此程式碼,並且稍後可能會覆寫此程式碼。這條規則需要取消前評論# BEGIN WordPress
標記。您無需重複RewriteEngine On
文件中稍後出現的指令(在 WordPress 部分)。
在測試之前,您需要清除瀏覽器緩存,因為錯誤的(永久)重定向可能已被瀏覽器快取。首先使用 301(臨時)重定向進行測試以避免快取問題。
但是,僅此一點並不允許您存取.php
沒有副檔名的檔案.php
。由於無副檔名 URL 需要在內部重寫回檔案.php
。