Эта тема на forum.dklab.ru


Марина Красильникова: mod_rewrite + передача скрипту большого количества параметров
уже второй день пытаюсь понять, как используя рекурсивность mod_rewrite, обработать большое количество параметров... то есть запрос вида /param1/param2/param0/param32/1param/againparam1/paramagain хочется преобразовать к виду script.php?var=param1-param2-param0-param32-1param-againparam1-paramagain
Не понимаю:( Объясните пожалуйста!

Заранее спасибо.
chin:
Как для меня, это тоже большая загдка. Пусть простят меня боги этого форума, но я приведу свой пример (как делал я). Уж не знаю, на сколько он практичен, но что ж тут поделаешь...

.htaccess:
ErrorDocument 404 /404.html
DirectoryIndex index.php
RewriteEngine on
RewriteCond %{THE_REQUEST} !\.css
RewriteCond %{THE_REQUEST} !\.jpg
RewriteCond %{THE_REQUEST} !\.gif
RewriteCond %{THE_REQUEST} !\.bmp
RewriteCond %{THE_REQUEST} !\.png
RewriteCond %{THE_REQUEST} !\?
RewriteRule ^(.*)$ index.php

далее в index.php получаю переменную $_SERVER['REQUEST_URI']
// Дублируем переменную для независимой работы со строкой запроса
$request = $_SERVER['REQUEST_URI'];
// Убираем первый слэш из строки адреса
if($request[0] === "/") $request = substr($request,1);
// делим строку по слэшам и создаем массив
$array = explode("/",$request);
// выводим массив (для теста)
var_dump($array);

таким образом, если мы вызовем этоу страницу, к примеру, вот так:
http://mysite.com/var1/var2/var3
То с таким скриптом, который я привел выше, мы получим вот такой ответ:
array(3) {
[0]=>
string(4) "var1"
[1]=>
string(4) "var2"
[2]=>
string(4) "var3"
}

Не знаю, на сколько это правильно, но, во всяком случае, хотябы работает (:
Марина Красильникова:
в принципе, алгоритм наверное должен выглядеть примерно так: проверяем (.*)/(.*), то есть остались ли еще там слэши, и заменяем на $1-$2... но если просто описать правило вида RewriteRule ^(.*)/(.*)$ script.php?var=$1-$2, то ни о какой рекурсии речь и не идет(точнее идет, но я ей не управляю), потому как подстановка сработает исключительно в случае запроса вида param1/param2.
Почерпнула в документации, что сначала проверяется шаблон из RewriteRule, затем проверяется RewriteCond, соответствующее этому правилу и лишь затем, в случае удачной проверки, в RewriteRule запускается подстановка. И получаются доступными не один тип карманов, как в случае наличия лишь RewriteRule, а два: $n - номер кармана в шаблоне RewriteRule и %n - номер кармана в строке-условии RewriteCond. стало быть, алгоритм приобретает более осмысленные очертания - просим RewriteRule проверить запрос на шаблон вида (.*)/(.*), в случае удачи управление переходит к RewriteCond. Здесь становится непонятно :). если написать

RewriteCond %{REQUEST_URI} (.*)/(.*)$
RewriteRule ^(.*)/(.*)$ %1-$2 [QSA]

, то mod_rewrite преобразовывает любой (практически) вложенности запрос вида param1/param2/param352/param3/etc в param1-param2-param352-param3-etc-, но тут возникает вопрос о том, как потом подставить результат скрипту? написав просто

RewriteCond %{REQUEST_URI} (.*)/(.*)$
RewriteRule ^(.*)/(.*)$ %1-$2 [QSA]

RewriteRule ^([^/]*-(.*))*$ script.php?args=$1 [L]

,мы рекурсивно обходя QUERY_STRING, будем справа налево заменять слэши на дефисы и получим $_SERVER['QUERY_STRING'] вида args=param1-param2-param352-param3-etc-
Но еще одно правило для избавления от одного дефиса в конце - это как-то чересчур... Нужно ограничить условие, дабы последний слэш не учитывался, но я что-то в ступоре.
Марина Красильникова:
совершенно улетучилось из головы то, что это все же рекурсия :)
Работающий пример:

#removes slash from the end of query_string
RewriteRule ^(.*)/$ $1 [L]
#recursive slash to minus replacement.
RewriteCond %{REQUEST_URI} (.*)/(.*)$
RewriteRule ^(.*)/(.*)$ %1-$2 [QSA]
#ready parameters redirect
RewriteRule ^([^/]*-(.*))*$ script.php?args=$1


воистину: "чтобы понять рекурсию, нужно сначала понять рекурсию"
chin:
Я вот только одного не понимаю.. Знающие, скажите пожалуйста, а неужели этот mod rewrite работает намного быстрее разборки на php? Ну, тут понятно, что без использования mod rewrite не обойтись... но неужели нельзя всю разборку и "рекурсию" повесить на php? Ведь mod rewrite является для апача тем же модулем, что и php. И работают они на одном уровне. Я не прав?
Марина Красильникова:
не прав. mod_rewrite работает до запуска обработчика содержания. и вообще - каждая программа должна делать свое дело, и делать его хорошо. А работает он действительно быстрее. Что Вы будете делать со стороны php для перенаправления на другую страницу? Посылать header("Location: ") ?
Дмитрий Котеров:
А я вот тоже считаю, что такие вещи надо делать на php, а не через mod_rewrite.
Все-таки возможности языка mod_rewrite очень сильно органичены, и большинство вещей там делается чрезмерно сложно.
Тем более, что в PHP-скрипте все равно потом придется бить строку по минусам. Какая разница, бить ее по минусам или сразу по слэшам?
Марина Красильникова:
суть-то не в минусах, а в том, что на входе скрипта посредством mod_rewrite можно получать гарантированно обрабатываемые данные.

Все-таки возможности языка mod_rewrite очень сильно органичены, и большинство вещей там делается чрезмерно сложно
Вы знаете, я когда впервые увидела RewriteRule, я вообще крепко задумалась, а стоит ли мне это изучать вообще. Тем не менее, как мне кажется, сфера применений именно mod_rewrite чрезвычайно широка.

Впрочем, если Вам покажется, что тему пора закрывать, я буду с Вами солидарна:)
Дмитрий Котеров:
У mod_rewrite есть один недостаток: каждая страница сайта становится, фактически, доступной по 2 разным URL: тому, что было до обработки mod_rewrite (ЧПУ), и тому, что получилось уже после обработки (с & и т.д.). Таким образом, с точки зрения поисковиков сайт может "раздвоиться" (если где-то будут случайно даны ссылки второго вида).
Юрий Насретдинов:
на входе скрипта посредством mod_rewrite можно получать гарантированно обрабатываемые данные
Гхм, ИМХО на mod_rewrite лучше вешать самый минимум, чтобы он просто «отдавал» всё главному скрипту на PHP, который бы дальше уже сам решал, как ему с полученным барахлом поступать. Возможности PHP намного шире, чем mod_rewrite, и не надо пытаться его использовать, когда есть намного более простой способ. mod_rewrite должен использоваться в полной мере там, где не вообще поддерживается PHP или Perl, и единственный способ хоть как-то управлять страницами - это SSI + mod_rewrite.
Марина Красильникова:
У mod_rewrite есть один недостаток: каждая страница сайта становится, фактически, доступной по 2 разным URL: тому, что было до обработки mod_rewrite (ЧПУ), и тому, что получилось уже после обработки (с & и т.д.). Таким образом, с точки зрения поисковиков сайт может "раздвоиться" (если где-то будут случайно даны ссылки второго вида).
У Вас на этом форуме сделано иначе?

Возможности PHP намного шире, чем mod_rewrite, и не надо пытаться его использовать, когда есть намного более простой способ
Как Вы с помощью php решите следующую задачу: есть сервер, доступный из интернета, при обращении к определенной "директории" все данные будут перенаправляться на другой сайт, недоступный из интернета и находящийся внутри локальной сети данного сервера?
Юрий Насретдинов:
Марина Красильникова
В данном случае без mod_rewrite будет тяжеловато. Микроскоп нужно использовать по его прямому назначению. Даже если очень аккуратно и со знанием дела очень аккуратно забивать им маленькие гвоздики, он всё равно настоящий молоток не заменит, и более того, не должен даже пытаться заменить
Марина Красильникова:
Юpий Насрeтдинов
Микроскоп и молоток изначально были предназначены для совершения абсолютно различных действий, и лишь микроскопом можно заменить молоток; а уже степень "заменяемости" и является поводом для употребления данного силлогизма. В нашем же случае действия, совершаемые php и mod_rewrite подчас взаимозаменяемы, но порой и практически уникальны. Потому я и говорю, что нужно рассматривать каждый конкретный случай в контексте множества применимых технологий.
Дмитрий Котеров:
У Вас на этом форуме сделано иначе?
Нет, не иначе - увы... Но это от бессилия - ибо тут движок phpBB.
Юрий Насретдинов:
Марина Красильникова
Фигню какую-то говорите, честное слово...
Марина Красильникова:
:) закрывайте тему, раз фигня
Юрий Насретдинов:
Тема закрыта.

Эта тема на forum.dklab.ru