2013-07-22 49 views
10

當我將多個RewriteCond鏈接在一起時,只有最後一個RewriteCond的捕獲組可以參考%0 - %9重寫規則中的多個RewriteCond的參考捕獲組

在以下問題中,url的查詢字符串中的參數可以以任意順序排列。爲了解析它們變成一個奇特的網址,我需要每一個參數在單獨的查詢字符串匹配:

RewriteCond %{QUERY_STRING} param1=([^&]+) 
RewriteCond %{QUERY_STRING} param2=([^&]+) 
RewriteCond %{QUERY_STRING} param3=([^&]+) 
RewriteRule ^foo$ bar/%1/%2/%3/ [R] 

就像我指出...這是行不通的。爲了解決這個問題,我可以引用前面的RewriteCond的捕獲組在接下來的RewriteCond和每個參數「傳播」實際重寫規則:

RewriteCond %{QUERY_STRING} param1=([^&]+) 
RewriteCond %1&%{QUERY_STRING} ^([^&]*)&.*param2=([^&]+) 
RewriteCond %1&%2&%{QUERY_STRING} ^([^&]*)&([^&]*)&.*param3=([^&]+) 
RewriteRule ^foo$ bar/%1/%2/%3/ [R] 

這應該工作,但是對於每個附加參數得到它的混亂。另一種解決方案可能是解析一個參數,並在每個參數後重定向客戶端(導致冗長的重定向鏈,這是我想避免的)。

是否有訪問的重寫規則所有的RewriteCond的捕獲組的更清潔的方式(例如,是否有可能給它們命名或將其分配給一個變量,所以我可以在其他地方引用它們?)

+2

+1的一個很大的問題。我也遇到了這個問題,並且很想知道答案 – anubhava

+0

mod_rewrite文檔說RewriteCond反向引用只保留當前條件集中最後一個匹配的RewriteCond **,所以,你的第二個答案可能是隻能在這條路線上回答。鑑於它的複雜性,你有沒有想過在'foo'上設置一個解析GET或POST的腳本並重定向到相應的'bar'? – miah

回答

10

你可以試試建設目標URL重寫條件中:

RewriteCond ##%{QUERY_STRING}  (.*)##(|.*&)param1=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param2=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param3=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param4=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param5=([^&]+) 
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param6=([^&]+) 

RewriteRule ^foo$ /bar%1/%3? [L,R] 

當我嘗試要求:

/foo?param1=a&param2=b&param6=3&param3=4&param5=5&param4=6

我重定向到:

/bar/a/b/4/6/5/3

添加任何額外的要求查詢字符串參數不會讓它看起來更多的凌亂比它已經是了。

+0

正在使用什麼'##'? –

+0

@RahilWazir它只是作爲一個分隔符來匹配,我們知道我們不能在uri中有'#',因此它可以安全使用 –

+0

所以這是必要的嗎?我的意思是沒有分隔符不會起作用(仍然不明白)? –

1

經過多次試驗後,可以將所有參數解析爲環境變量並像這樣使用它們。我懷疑它是非常有效的,但我認爲任何需要這種構造的用例都會更好地使用php頁面路由器。對於花哨的url,Jon Lin的解決方案可能會更好。但它確實有點模仿我心中的想法。

我會,但是,將代碼放在這裏演示:

#Parse all query key-value pairs to an environment variable with the q- prefix 
RewriteCond %{QUERY_STRING} ^([^=]*)=([^&]*)(&(.*)|$)$ 
RewriteRule ^(.*)$ $1?%4 [E=q-%1:%2,N] 

#If 'param1' existed in the query string... 
RewriteCond %{ENV:q-param1} !^$ 
RewriteRule ^foo$ bar/%{ENV:q-param1} [END] 

甚至...

#Keep the original query string 
RewriteCond %{ENV:qstring} ^$ 
RewriteCond %{QUERY_STRING} ^(.*)$ 
RewriteRule .* - [E=qstring:#%1] 

#parse the query parameters to environment variables 
RewriteCond %{ENV:qstring} ^#([^=]*)=([^&]*)(&(.*)|$)$ 
RewriteRule ^(.*)$ - [E=q-%1:%2,E=qstring:#%4,N] 

#See that the original query string is still intact 
RewriteCond %{ENV:q-param1} !^$ 
RewriteRule ^foo$ bar/%{ENV:q-param1} [QSA]