Подтвердить что ты не робот

RewriteCond для сопоставления параметров строки запроса в любом порядке

У меня есть URL-адрес, который может содержать три параметра:

  • ? Категория = компьютеры
  • &ampы; подкатегория = ноутбуки
  • & продукт = лощина-Инспирон-15

Мне нужно 301 перенаправить этот URL в его дружественную версию:

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]
4b9b3361

Ответ 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 и двойного условия, вы можете использовать

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

как предположил @TrueBlue.

Другим подходом является префикс TestString QUERY_STRING с амперсандом & и всегда проверять

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

Этот метод (префикс TestString) также может использоваться для переноса уже найденных параметров на следующий RewriteCond. Это позволяет нам упростить три правила только одному

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.

Ответ 2

Я использую несколько иной подход для такого рода вещей, , используя 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 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]

P.S. Это не решение для копирования и вставки для вашего вопроса, а скорее показывает именно как для решения этой проблемы. Вооруженное это понимание, используя его для вашего примера, будет совершенно тривиально.:)