你能在我的 .htaccess 中看到什麼問題嗎?
我已經設法創建了一個
.htaccess
文件,可以滿足我的要求(請參閱程式碼塊後的解釋和問題):<IfModule mod_rewrite.c> RewriteEngine On #1 If the requested file is not url-mapper.php (to avoid .htaccess loop) RewriteCond %{REQUEST_FILENAME} (?<!url-mapper\.php)$ #2 If the requested URI does not end with an extension OR if the URI ends with .php* RewriteCond %{REQUEST_URI} !\.(.*) [OR] RewriteCond %{REQUEST_URI} \.php.*$ [NC] #3 If the requested URI is not in an excluded location RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)(/.*)?$ #Then serve the URI via the mapper RewriteRule .* /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA] </IfModule>
這是
.htaccess
應該做的:
- Rule#1正在檢查請求的文件是否不是
url-mapper.php
(以避免無限重定向循環)。此文件將始終位於域的根目錄。- 規則#2
.htaccess
必須只擷取不以副檔名結尾的 URL ( –www.example.com
> catch |www.example.com/catch-me
–> catch |www.example.com/dont-catch.me
–> don’t catch)和.php\*
以文件結尾的 URL (.php
,.php4
,.php5
,.php123
, …)。- 規則#3一些目錄(和子目錄)可以從
.htaccess
(在這種情況下/seo-urls/excluded1
和/seo-urls/excluded2
)中排除。- 最後,
.htaccess
向映射器提供一個隱藏的GET 參數,該參數名為uri
包含請求的 URI。即使我進行了測試並且一切正常,我也想知道我所做的是否正確(以及它是否是“最好的”方法)。我從這個“項目”中學到了很多東西,但我仍然認為自己是
.htaccess
正則表達式的初學者,所以我想在將其投入生產之前對其進行三次檢查……
2a 將允許 /some.dir/file 因為“。” 在中間。您可能想要類似的東西
!\..[1,3]
,這取決於您的文件/目錄結構。在 RewriteRules 中,使用替換匹配而不是變數名是正常的:
RewriteRule (.*) /seo-urls/url-mapper.php?uri=$5 [L,QSA]
注意這是
$5
因為您目前在您的條件中都有匹配模式。
<IfModule mod_rewrite.c>
不需要
<IfModule>
包裝器。在網站管理員堆棧上查看此問題: https ://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary#1 If the requested file is not url-mapper.php (to avoid .htaccess loop) RewriteCond %{REQUEST_FILENAME} (?<!url-mapper\.php)$
不需要消極的後視 (
(?<!
)。最好簡單地使用一個否定的正則表達式。IE。帶!
前綴。例如:!^/url-mapper\.php$
(ie. not “/url-mapper.php”) 並檢查REQUEST_URI
(full URL-path) 而不是REQUEST_FILENAME
(absolute filesystem path)。但是,您聲明“此文件將始終位於域的根目錄”,但您正在重寫
/seo-urls/url-mapper.php
- 它不在域的根目錄。所以,這應該嚴格地寫成這樣:
RewriteCond %{REQUEST_URI} !^/seo-urls/url-mapper\.php$
除非您確信
url-mapper.php
系統上只有一個文件,否則正則表達式可以簡化為!/url-mapper\.php$
.或者,改為在
RewriteRule
模式中檢查這一點(因為您目前沒有對RewriteRule
模式執行任何其他操作)。這會稍微更有效率。#2 If the requested URI does not end with an extension OR if the URI ends with .php* RewriteCond %{REQUEST_URI} !\.(.*) [OR] RewriteCond %{REQUEST_URI} \.php.*$ [NC]
第一個條件太籠統了——它擷取任何在 URL 路徑中任何地方都包含一個點的 URL,而不僅僅是文件副檔名。也不需要擷取子模式。假設文件副檔名介於 2 到 4 個字元之間,那麼類似的模式
!\.\w{2,4}$
將更準確地僅擷取文件副檔名。正則表達式通常應盡可能嚴格。匹配 副檔名的第二個條件
.php
可以更加嚴格,它目前匹配URL 路徑中的.php
*任何位置。*例如:\.php\d{0,4}$
- 雖然實際上,您可能最多只有 1 位數字.php
,所以\.php\d?$
可能會更好。我還質疑
NC
這裡是否真的需要(不區分大小寫)標誌。你真的需要匹配嗎.PHP
?.PhP
#3 If the requested URI is not in an excluded location RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)(/.*)?$
好的,但尾隨
(/.*)?$
是多餘的。您正在匹配任何簡單開始/seo-urls/excluded1
等的內容。此外,無需反斜杠轉義斜杠(好奇您已經轉義了中間斜杠,但不是其他兩個)。#Then serve the URI via the mapper RewriteRule .* /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]
好的,雖然正則表達式
.*
(匹配所有內容)可以簡化為^
- 這對所有內容都是成功的,但實際上並不匹配任何內容 - 這就是您所需要的。但是,我在頂部提到了在模式
url-mapper.php
中執行檢查。所以,這將被寫成:RewriteRule
RewriteRule !^seo-urls/url-mapper\.php$ /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]
在任何條件之前首先處理
RewriteRule
模式,因此最好在RewriteRule
指令中執行您可以執行的操作,而不是將其分離到另一個條件中。概括
綜合以上幾點,我們有:
RewriteEgnine On #2 If the requested URI does not end with an extension OR if the URI ends with .php* RewriteCond %{REQUEST_URI} !\.\w{2,4}$ [OR] RewriteCond %{REQUEST_URI} \.php\d?$ #3 If the requested URI is not in an excluded location RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2) #Then serve the URI via the mapper RewriteRule !^seo-urls/url-mapper\.php$ /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [QSA,L]