Рекурсивный mod_rewrite для URL-адресов, удобных для поисковых систем.

Я читал предыдущее решение к рекурсивной проблеме mod_rewrite, которая похожа на то, что я пытаюсь сделать, разница в том, что я отправляю все запросы через файл index.php, поэтому мне не нужно указывать скрипт в запросе.

По сути, я хочу рекурсивно преобразовать любое количество параметров в URL-адрес, удобный для поисковой системы:

example.com/param1/val1/param2/val2/...

в обычную строку запроса:

example.com/index.php?param1=val1&param2=val2&...

До сих пор мои попытки не увенчались успехом:

RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^([^/]+)/([^/]+) $1=$2&%1 [L]
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)$ index.php?%1 [L]

Может ли кто-нибудь предложить какие-либо предложения?


person dGreaves    schedule 08.12.2009    source источник


Ответы (4)


Я скопировал решение из этого другого вопроса и изменил его следующим образом:

RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*/)?([^/]+)/([^/]+) $1?$2=$3&%1 [L]
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^.*$ index.php?%1 [L]

Он делает почти то же самое, за исключением того, что в первом правиле первое совпадение является необязательным, а во втором правиле совпадение происходит с тем, что осталось после сопоставления всех остальных пар.

При нечетном количестве параметров первый параметр игнорируется.

Одно замечание: если вы ожидаете, что у вас будет много параметров, вам, возможно, придется изменить некоторые настройки.

Добавьте что-то подобное в ваш файл .htaccess.

RewriteOptions MaxRedirects=20

и что-то подобное в ваш файл конфигурации apache

LimitInternalRecursion 20

Вместо «20» выберите любое количество рекурсий (пар), которое вам нужно разрешить (по умолчанию — 10).

person bmb    schedule 08.12.2009
comment
Он хорошо работает для четного числа параметров (хотя и не распознает нечетное число). Спасибо за внимание, очень приятно ;-) - person dGreaves; 08.12.2009
comment
dGreaves, я не уверен, что вы хотите делать с нечетным количеством параметров. Измените ^$ на ^.*$ в последней строке, и, по крайней мере, это не приведет к ошибке. - person bmb; 08.12.2009
comment
Гамбо, лол. Думаю, я мог бы быть яснее. Я надеюсь, что новое редактирование ответит на ваш вопрос. - person bmb; 09.12.2009

Я понимаю, что это очень старая тема. Но поскольку ни один из ответов, размещенных здесь, не сработал для меня, и я хочу опубликовать свой ответ, чтобы посетители могли использовать его, если захотят, поэтому я отвечаю здесь:

Options +FollowSymlinks -MultiViews
RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)(/.*)?$ $3?$1=$2 [N,QSA,DPI]
RewriteRule ^(/[^/]+|[^/]+/|/?)$ /index.php [L,QSA,DPI]

Для получения более подробной информации см. мой ответ на MOD_REWRITE для переменных URL, удаление пустых параметров и использование более 1 поля для первой и второй переменных

person anubhava    schedule 27.04.2011

да...

Взято из примеров здесь:

http://iirf.codeplex.com/sourcecontrol/changeset/view/62027?projectName=IIRF#981491

Этот набор правил итеративно преобразует пару сегментов пути URL в сегмент строки запроса n=v.

# handle case with no query string.  This rule fires the first time through,
# and converts the first pair of URL path segments to a n=v query string segment.  
RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)/([^\?]+)$ /$3?$1=$2

# handle the case where there is an existing query string, and more than one pair of 
# URL path segments remaining. This rule fires potentially multiple times.
RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)/([^\?]+)\?(.+)$ /$3?$4&$1=$2


# Handle the case with a query string, and exactly one pair of URL path segments. 
# This fires once (last).
# It fires when there is an even number of segments. 
RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)\?([^\?]+)$ /help.cfm?$3&$1=$2  [L]

# Handle the case with no query string, and exactly one pair of URL path segments. 
# This fires once (last).
RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)$ /help.cfm?$1=$2  [L]


# Handle the edge case, where there is an odd number of segments, which is invalid
# for these purposes. 
#
# This fires once, after all the other pairs have been parsed.  In fact the filter
# cannot know that there is an odd number of segments until it does all the matching.
# So at the end we see, we have one left over segment, and we 
# redirect to a 404 page.

RewriteRule ^/(?!index\.php)([^\/\?]+)\?([^\?]+)$ /ResourceNotFound.php  [L]

# Handle the edge case where there is only one segment. This is also an error
# in this ruleset.
RewriteRule ^/(?!index\.php)([^\/\?]+)$ /FoundOnlyOneSegment.php  [L]

Этот набор правил может быть не совсем тем, что вам нужно, но он иллюстрирует подход. Он был разработан не для mod_rewrite, а для IIRF, который является переписчиком для IIS. Но синтаксис для mod_rewrite должен быть таким же, так что эти правила должны работать.

Я не знаю, есть ли у mod_rewrite средство ведения журнала или возможность тестирования из командной строки, но IIRF имеет, что упрощает просмотр того, как работают отдельные правила, или результаты наборов правил.

У IIRF есть предел итераций, который по умолчанию равен 10. Есть способ поднять этот предел до 30, что довольно много, но все же не бесконечно. Это означает, что он не будет работать для «любого количества параметров». Он может преобразовать до 15 пар параметров. Я не знаю, есть ли у mod_rewrite аналогичный лимит.

person Cheeso    schedule 08.12.2009

Попробуйте эти правила:

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
RewriteRule ^([^/]+)/([^/]+)(/(.*))?$ /$4?$1=$2 [N,QSA]
RewriteRule ^$ index.php [L]

Первое правило — исключить запросы к существующим файлам. Второе правило сделает всю работу и перепишет каждую пару имя-значение. И третье правило — переписать окончательный URI на index.php.

person Gumbo    schedule 08.12.2009
comment
Привет, спасибо за ответ, это работает нормально для 2 параметров запроса, но, похоже, не распознает больше? - person dGreaves; 08.12.2009
comment
Гамбо, я думаю, что ваше правило, которое работает, должно иметь «L» вместо «N» и не использовать косую черту перед $4: RewriteRule ^([^/]+)/([^/]+)(/(.*))?$ $4?$1=$2 [L,QSA] - person bmb; 09.12.2009
comment
@bmb: Нет, это должно быть именно так. - person Gumbo; 09.12.2009