web-dev-qa-db-ja.com

クエリ文字列パラメーターを任意の順序で照合するためのRewriteCond

3つのパラメータを含むURLがあります。

  1. ?category = computers
  2. &subcategory = laptops
  3. &product = Dell-inspiron-15

このURLをフレンドリーなバージョンに301リダイレクトする必要があります。

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

私はこれを持っていますが、クエリ文字列パラメーターが他の順序である場合は機能しません:

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

これは、1つのパラメーターを検出して次のステップに転送し、最終的な宛先にリダイレクトすることにより、複数のステップで実現できます。

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]

ORおよびdouble条件を回避するには、次を使用できます

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

@TrueBlueが示唆したように。

別のアプローチは、TestStringQUERY_STRINGの前にアンパサンド&を付け、常にチェックすることです

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

この手法(TestStringのプレフィックス)は、すでに見つかったパラメーターを次の RewriteCond に繰り越すためにも使用できます。 =。これにより、3つのルールを1つに簡略化できます

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]

!は、既に見つかって並べ替えられたパラメーターをQUERY_STRINGから分離するためにのみ使用されます。

16
Olaf Dietsche

この種のものには少し異なるアプローチをとっていますENV VARを利用し、mod_rewriteによって読み取られます。このように名前で後方参照を参照する方が読みやすく、保守しやすいと思います。これらのENV VARは、後で要求処理でも再利用できます。全体として、ここで認められている答えよりも強力で柔軟なアプローチだと思います。いずれにしても、それは私にはうまくいきます。以下の要点を完全にコピーしました。

から 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]

追伸これはあなたの質問のコピー/貼り付け可能な解決策ではなく、この種の問題を処理する正確な方法を示しています。この理解を武器にして、あなたの例にそれを活用することは完全に簡単です。 :)

3
cweekly

1)すべてのパラメーターがurlにあることを確認する必要がある場合:

   RewriteCond %{QUERY_STRING} (^|&)category\=computers($|&)
   RewriteCond %{QUERY_STRING} (^|&)subcategory\=laptops($|&)
   RewriteCond %{QUERY_STRING} (^|&)product\=Dell\-inspiron\-15($|&)
   RewriteRule ^$ http://store.example.com/computers/laptops/Dell-inspiron-15/? [R=301,L]

2)パラメータの正確なセットが必要な場合:

 RewriteCond %{QUERY_STRING} ^&*(?:category\=computers|subcategory\=laptops|product\=Dell\-inspiron\-15)(?!.*&\1(?:&|$))(?:&+(category\=computers|subcategory\=laptops|product\=Dell\-inspiron\-15)(?!.*&\1(?:&|$))){2}&*$
 RewriteRule ^$ http://store.example.com/computers/laptops/Dell-inspiron-15/? [R=301,L] 

このルールは 301リダイレクトジェネレーター によって生成されます

0
Res Pro