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

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

например, у меня сейчас есть:

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

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

Ответы [ 3 ]

8 голосов
/ 23 сентября 2008

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

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

Установите правило, которое заменяет последнюю пару именем = значение &

Продолжайте привязывать строку входного запроса к выходу. Каждый раз, когда ваша строка запроса будет становиться длиннее, а ваш 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 не ограничено.

8 голосов
/ 23 сентября 2008

Do like 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++;
    }
}
2 голосов
/ 23 сентября 2008

Я не верю, что это способ, но я бы сказал, что лучше всего было бы, чтобы скрипт «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'

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...