Перезапись произвольного числа сегментов пути в параметры запроса
У меня есть это правило.htaccess:
RewriteRule viewshoplatest/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/$ /viewshoplatest.php?$1=$2&$3=$4&$5=$6&$7=$8&$9=$10&$11=$12&$13=$14&$15=$16
Он должен сопоставить URL-адрес следующим образом:
http://www.veepiz.com/viewshoplatest/start/10/end/10/filter/0/ownerid/0/sortby/date/sortdir/DESC/cat/0/scat/0/
к этому:
http://www.veepiz.com/viewshoplatest.php?start=0&end=10&filter=0&ownerid=0&sortby=date&sortdir=DESC&cat=0&scat=0
Когда я нажимаю на ссылку и распечатать $_GET
переменные я получаю это:
Array ( [start] => 10 [end] => 10 [filter] => 0 [ownerid] => 0 [sortby] => start0 [start1] => start2 [start3] => start4 [start5] => start6 )
Есть идеи, почему он ведет себя плохо?
Хорошо, я исправил это, переписав правило
RewriteRule viewshoplatest/start/(.*)/end/(.*)/filter/(.*)/ownerid/(.*)/sortby/(.*)/sortdir/(.*)/cat/(.*)/scat/(.*)/$ /viewshoplatest.php?start=$1&end=$2&filter=$3&ownerid=$4&sortby=$5&sortdir=$6&cat=$7&scat=$8
2 ответа
Прежде всего: вы не должны использовать .*
если вы можете быть более конкретным, как в этом случае [^/]+
, Потому что несколько .*
может вызвать огромный откат назад. Так:
RewriteRule ^viewshoplatest/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/$ /viewshoplatest.php?$1=$2&$3=$4&$5=$6&$7=$8&$9=$10&$11=$12&$13=$14&$15=$16
Вы можете использовать take как RegexBuddy, чтобы увидеть разницу в обработке этих регулярных выражений.
Но поскольку mod_rewrite позволяет ссылаться только на первые девять групп (см . Ответ Тима), вы можете использовать итеративный подход и обрабатывать один параметр за раз:
RewriteRule ^viewshoplatest/([^/]+)/([^/]+)/([^/]+/[^/]+/.*)$ /viewshoplatest/$3?$1=$2 [QSA,N]
RewriteRule ^viewshoplatest/([^/]+)/([^/]+)/([^/]*)/?$ /viewshoplatest.php?$1=$2&$3 [QSA,L]
Первое правило будет обрабатывать одну пару параметров за раз (кроме последней пары), добавляя ее к уже существующим (см. Флаг QSA), а затем перезапуская процесс перезаписи, не увеличивая внутренний счетчик рекурсии (см. Флаг N). Затем второе правило перезапишет последнюю пару параметров (или только имя) и завершит итерацию.
Но поскольку использование флага N может быть опасным, поскольку может вызвать бесконечную рекурсию, вы также можете использовать PHP для анализа запрошенного пути:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = implode('/', trim($_SERVER['REQUEST_URI_PATH'], '/'));
array_shift($segments); // remove path prefix "/viewshoplatest"
for ($i=0, $n=count($segments); $i<$n; ) {
$_GET[rawurldecode($segments[$i++])] = ($i < $n) ? rawurldecode($segments[$i++]) : null;
}
Теперь вам просто нужно это правило для прохождения запроса:
RewriteRule ^viewshoplatest(/|$) /viewshoplatest.php [L]
Просто чтобы раскрыть то, что вы обнаружили, вы можете определить только девять групп, которые будут использоваться в качестве обратных ссылок, поэтому обычно лучше переписать строку сценария sans-query и проверить его. REQUEST_URI
в тех случаях, когда у вас будет много данных для анализа.
Из документации:
Обратные ссылки - это идентификаторы вида $N (N=0..9), которые будут заменены содержимым N-й группы соответствующего шаблона.
$0
это весь подобранный шаблон, предоставляющий вам оставшиеся девять чисел для работы. Любое большее число рассматривается как обратная ссылка, за которой следуют некоторые буквенные числовые символы.