2013-01-13 27 views
11

Tôi có một URL có thể chứa ba thông số:RewriteCond để phù hợp với các thông số chuỗi truy vấn trong bất kỳ thứ tự

  1. category = máy tính
  2. & tiểu thể loại = laptop
  3. sản phẩm & = dell-inspiron-15

Tôi cần 301 chuyển hướng URL này đến phiên bản thân thiện của nó:

http://store.example.com/computers/laptops/dell-inspiron-15/ 

Tôi có điều này nhưng không thể làm cho nó hoạt động nếu các thông số chuỗi truy vấn là trong bất kỳ thứ tự khác:

RewriteCond %{QUERY_STRING} ^category=(\w+)&subcategory=(\w+)&product=(\w+) [NC] 
RewriteRule ^index\.php$ http://store.example.com/%1/%2/%3/? [R,L] 
+0

Giải pháp dễ nhất là để PHP thực hiện chuyển hướng. – Gerben

+0

@Gerben giả sử một người đang sử dụng PHP ...câu hỏi đã được cụ thể cho apache, có thể được sử dụng với bất kỳ số ngôn ngữ/khuôn khổ/etc. Đúng, sử dụng PHP (hoặc bất kỳ ngôn ngữ lập trình hoặc kịch bản nào khác) để thao tác các tham số URL có một số ưu điểm, nhưng câu hỏi này đặc biệt về apache/mod_rewrite. –

+0

Trong trường hợp cụ thể này, OP dường như đang sử dụng PHP, vì RewriteRule chứa index.php. – Gerben

Trả lời

15

Bạn có thể đạt được điều này với nhiều bước, bằng cách phát hiện một tham số và sau đó chuyển tiếp sang bước tiếp theo và sau đó chuyển hướng đến đích cuối cùng

RewriteEngine On 

RewriteCond %{QUERY_STRING} ^category=([^&]+) [NC,OR] 
RewriteCond %{QUERY_STRING} &category=([^&]+) [NC] 
RewriteRule ^index\.php$ $0/%1 

RewriteCond %{QUERY_STRING} ^subcategory=([^&]+) [NC,OR] 
RewriteCond %{QUERY_STRING} &subcategory=([^&]+) [NC] 
RewriteRule ^index\.php/[^/]+$ $0/%1 

RewriteCond %{QUERY_STRING} ^product=([^&]+) [NC,OR] 
RewriteCond %{QUERY_STRING} &product=([^&]+) [NC] 
RewriteRule ^index\.php/([^/]+/[^/]+)$ http://store.example.com/$1/%1/? [R,L] 

để tránh tình trạng đôi OR và, bạn có thể sử dụng

RewriteCond %{QUERY_STRING} (?:^|&)category=([^&]+) [NC] 

như @TrueBlue đề xuất.

cách tiếp cận khác là tiền tố TestStringQUERY_STRING bằng ký hiệu &, và kiểm tra luôn

RewriteCond &%{QUERY_STRING} &category=([^&]+) [NC] 

Kỹ thuật này (tiền tố các TestString) cũng có thể được sử dụng để thực hiện chuyển tiếp đã được tìm thấy thông số cho RewriteCond tiếp theo. Điều này cho phép chúng ta đơn giản hóa ba quy tắc để chỉ một

RewriteCond &%{QUERY_STRING} &category=([^&]+) [NC] 
RewriteCond %1!&%{QUERY_STRING} (.+)!.*&subcategory=([^&]+) [NC] 
RewriteCond %1/%2!&%{QUERY_STRING} (.+)!.*&product=([^&]+) [NC] 
RewriteRule ^index\.php$ http://store.example.com/%1/%2/? [R,L] 

Các ! chỉ được sử dụng để tách các thông số đã được tìm thấy và sắp xếp lại từ QUERY_STRING.

+0

Trên quy tắc đầu tiên, url được thay đổi thành ví dụ: '/ computers /'. Không nên kiểm tra quy tắc tiếp theo cho '/ \ w + /' thay vì index.php? –

+0

@SalmanA Quy tắc đầu tiên thay đổi URL thành 'index.php/computers'. Vì vậy, quy tắc tiếp theo phải kiểm tra 'index.php/...'. Tôi đã sửa mẫu thành 'index.php/[^ /] +'. –

+0

Tôi đã làm cho nó hoạt động với các chỉnh sửa nhỏ (ví dụ: sử dụng '(?:^| &)' Để loại bỏ mệnh đề OR). – TrueBlue

3

Tôi có cách tiếp cận hơi khác so với loại điều này, tận dụng ENV VAR được đặt và đọc bởi mod_rewrite. Tôi tìm thấy nó dễ đọc hơn/có thể duy trì để tham khảo các backreferences theo tên như thế này, và các VAR ENV có thể được tái sử dụng sau này trong xử lý yêu cầu quá. Nói chung tôi nghĩ đó là một cách tiếp cận mạnh mẽ và linh hoạt hơn câu trả lời được chấp nhận ở đây. Trong mọi trường hợp, nó hoạt động tốt cho tôi. Tôi đã sao chép ý chính của tôi dưới đây trong toàn bộ:

Từ https://gist.github.com/cweekly/5ee064ddd551e1997d4c

# Mod_rewrite is great at manipulating HTTP requests. 
# Using it to set and read temp env vars is a helpful technique. 
# 
# This example walks through fixing a query string: 
# Extract good query params, discard unwanted ones, reorder good ones, append one new one. 
# 
# Before: /before?badparam=here&baz=w00t&foo=1&bar=good&mood=bad 
# After: /after?foo=1&bar=good&baz=w00t&mood=happy 
# 
# Storing parts of the request (or anything you want to insert into it) in ENV VARs is convenient. 
# Note the special RewriteRule target of "-" which means "no redirect; simply apply side effects" 
# This lets you manipulate the request at will over multiple steps. 
# 
# In a RewriteRule, set custom temp ENV VARs via [E=NAME:value] 
# Note it's also possible to set multiple env vars 
# like [E=VAR_ONE:hi,E=VAR_TWO:bye] 
# 
# You can read these values using %{ENV:VAR_NAME}e <- little "e" is not a typo 
# 
# Tangent: 
# Note you can also read these env vars the same way, if you set them via SetEnvIf[NoCase] 
# (It won't work to use SetEnv, which runs too early for mod_rewrite to pair with it.) 
# 
# Regex details: 
# (?:) syntax means "match but don't store group in %1 backreference" 
#  so (?:^|&) is simply the^beginning or an & delimiter 
#  (the only 2 possibilities for the start of a qs param) 
# ([^&]+) means 1 or more chars that are not an & delimiter 

RewriteCond %{QUERY_STRING} (?:^|&)foo=([^&]+) 
RewriteRule ^/before - [E=FOO_VAL:%1] 

RewriteCond %{QUERY_STRING} (?:^|&)bar=([^&]+) 
RewriteRule ^/before - [E=BAR_VAL:%1] 

RewriteCond %{QUERY_STRING} (?:^|&)baz=([^&]+) 
RewriteRule ^/before - [E=BAZ_VAL:%1] 

RewriteRule ^/before /after?foo=%{FOO_VAL}e&bar=%{BAR_VAL}e&baz=%{BAZ_VAL}e&mood=happy [R=301,L] 

T.B. Đây không phải là giải pháp sao chép/có thể dán cho câu hỏi của bạn, mà là hiển thị chính xác cách để xử lý loại sự cố này. Được trang bị với sự hiểu biết này, tận dụng nó cho ví dụ của bạn sẽ hoàn toàn tầm thường. :)

Các vấn đề liên quan