apache mod_rewrite одно правило для любого количества возможностей

StackOverflow https://stackoverflow.com/questions/117931

  •  02-07-2019
  •  | 
  •  

Вопрос

Я создаю довольно большой веб-сайт, и мой .htaccess начинает казаться немного раздутым, есть ли способ заменить мою текущую систему из одного правила для каждого из возможного количества переменных, которые могут быть переданы, на одно выражение catch all, которое может учитывать различное количество входных данных?

например, в настоящее время у меня есть:

RewriteRule ^([a-z]+)/([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)$ /index.php?mode=$1&id=$2&$3=$4&$5=$6
RewriteRule ^([a-z]+)/([^/]*)/([^/]*)/([^/]*)$ /index.php?mode=$1&id=$2&$3=$4
RewriteRule ^([a-z]+)/([^/]*)$ /index.php?mode=$1&id=$2
RewriteRule ^([a-z]+)$ /index.php?mode=$1

первая обратная ссылка всегда является режим и (если таковые еще существуют) второй всегда ID, после этого любые дальнейшие обратные ссылки чередуются между именем входных данных и их значением

http://www.example.com/search
http://www.example.com/search/3039/sort_by/name_asc/page/23

Мне бы очень хотелось иметь одно выражение для изящной обработки всех входных данных.

Это было полезно?

Решение

Нравится ли вам Drupal:

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

А затем обработайте все содержимое вашего скрипта, используя php-код, что-то вроде этого

$pathmap = ();
if ($_GET["q"]){
    $path = split("/", $_GET["q"]);
    for ($i=0; $i+1<count($path); $i++){
        $pathmap[$path[$i]] = $path[$i+1];
        $i++;
    }
}

Другие советы

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

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

Настройте правило, которое заменяет последнюю пару на name=value&

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

В конечном итоге у вас есть только одно значение, соответствующее вашему последнему правилу.

Вы должны записать строку запроса с помощью

RewriteCond %{QUERY_STRING} ^(.*)$

А затем вы добавляете его обратно в выходные данные с помощью %1

В итоге у вас получилось бы четыре строчки.

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

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

Это приведет к перезаписи следующего

/mypage/param1/val1/param2/val2/param3/val3/...     --->
/mypage.php?param1=val1&param2=val2&param3=val3&...

Он останавливается, когда остается только один параметр.Он примет первый "параметр" и вызовет php-файл с этим именем.Количество пар param / val не ограничено.

Я не верю, что это способ, но я бы сказал, что лучше всего было бы, чтобы скрипт "index.php" обрабатывал путь вместо того, чтобы делать так много обратных ссылок.

Так, например, ваш rewriterule будет выглядеть

RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

Или что-то подобное...Затем это заставило бы переменную $_SERVER['REQUEST_URI'] содержать информацию о пути, которую вы можете разделить и проанализировать.

$path = split('/', $_SERVER['REQUEST_URI']);
array_shift($path); // We always have a first null value
$mode = array_shift($path);

В итоге получается $mode, содержащий mode, и $path, содержащий массив элементов, которые являются остальной частью вашего пути, так что

http://example.com/foo/bar/baz

Это привело бы к тому, что $mode был бы 'foo', а $path - массивом, содержащим 'bar' и 'baz'

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top