12

我正在建立一个相当大的网站,我的 .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

我希望能够有一个表达式来优雅地处理所有输入。

4

3 回答 3

9

喜欢 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++;
    }
}
于 2008-09-22T22:17:16.097 回答
8

我不知道它是否可以用单个表达式来完成,但它可以用固定数量的表达式来完成,不管查询字符串有多长。

您的 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&...

It stops when there is only one parameter remaining. It will take the first "parameter" and call the .php file with that name. There is no limit to the number of param/val pairs.

于 2008-09-23T05:48:14.517 回答
2

我不相信他们是一种方式 - 但我会说你最好的选择是让脚本“index.php”处理一个路径,而不是做这么多的反向引用。

因此,例如,您的重写将是

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 和包含作为路径其余部分的元素数组的 $path 结束,所以

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

会让你留下 $mode 是 'foo' 而 $path 是一个包含 'bar' 和 'baz' 的数组

于 2008-09-22T22:20:15.137 回答