2013-07-22 27 views
10

Khi tôi có nhiều RewriteCond xích lại với nhau, chỉ các nhóm chụp của RewriteCond mới có thể được tham chiếu với %0 - %9.Các nhóm chụp tham chiếu của nhiều RewriteCond trong RewriteRule

Trong sự cố sau, các tham số trong chuỗi truy vấn của url có thể theo bất kỳ thứ tự nào. Để phân tích chúng thành một url lạ mắt, tôi cần phải đối sánh từng thông số trong chuỗi truy vấn riêng lẻ:

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

Như tôi đã chỉ ra ... điều này không hiệu quả. Để sửa lỗi này, tôi có thể tham khảo các nhóm chụp của RewriteCond trước đó trong RewriteCond tiếp theo và 'tuyên truyền' mỗi tham số cho RewriteRule thực tế:

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

này nên làm việc, nhưng đối với mỗi tham số bổ sung nó lấy của Messier. Một giải pháp khác có thể phân tích cú pháp một tham số và chuyển hướng máy khách sau mỗi tham số (dẫn đến một chuỗi các chuyển hướng dài, mà tôi muốn tránh).

Có một cách sạch tiếp cận các nhóm bắt giữ tất cả của RewriteCond trong RewriteRule (ví dụ như là nó có thể để đặt tên họ hay gán chúng cho một biến vì vậy tôi có thể tham khảo chúng ở một nơi khác?)

+2

+1 cho một câu hỏi lớn. Tôi cũng đã phải đối mặt với vấn đề này, và sẽ muốn biết câu trả lời – anubhava

+0

Các tài liệu mod_rewrite nói rằng RewriteCond backreferences chỉ giữ lại ** trùng khớp lần cuối ** trong tập hợp điều kiện hiện tại, vì vậy, vâng, câu trả lời thứ hai của bạn có thể là chỉ trả lời trong tuyến đường này. Do sự phức tạp của nó, bạn có nghĩ về việc thiết lập một kịch bản tại 'foo' phân tích cú pháp GET) hoặc POST) và chuyển hướng đến' bar' thích hợp không? – miah

Trả lời

10

Bạn có thể thử xây dựng URL mục tiêu bên trong điều kiện viết lại:

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] 

Khi tôi cố gắng yêu cầu:

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

tôi được chuyển đến:

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

Thêm bất kỳ cần thông số chuỗi truy vấn bổ sung sẽ không làm cho nó trông bất kỳ lộn xộn hơn nó đã là.

+0

'##' đang được sử dụng để làm gì? –

+0

@RahilWazir nó chỉ được sử dụng như một dấu phân cách để phù hợp với, chúng tôi biết chúng tôi không thể có '#' 's trong uri vì vậy nó an toàn để sử dụng –

+0

Vì vậy, điều này là cần thiết? Tôi có nghĩa là không có delimiters sẽ không làm việc (vẫn không hiểu)? –

1

Sau khi thử nghiệm một số chi tiết khác, bạn có thể phân tích cú pháp tất cả các tham số dưới dạng biến môi trường và sử dụng chúng như vậy. Tôi nghi ngờ nó là rất hiệu quả mặc dù và tôi nghĩ rằng bất kỳ trường hợp sử dụng mà sẽ cần xây dựng như vậy sẽ tốt hơn bằng cách sử dụng một bộ định tuyến trang php. Đối với giải pháp của Jon Lin's url ưa thích có lẽ sẽ hoạt động tốt hơn. Tuy nhiên nó lại giống như những gì tôi nghĩ.

Tôi sẽ, tuy nhiên, đặt đoạn code trong đây để trình diễn:

#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] 

hoặc thậm chí ...

#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] 
Các vấn đề liên quan