【问题标题】:apache mod_rewrite one rule for any number of possibilitiesapache mod_rewrite 一条规则,适用于任意数量的可能性
【发布时间】:2010-09-12 04:30:56
【问题描述】:

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

第一个反向引用总是 mode 并且(如果有的话)第二个总是 id,此后任何进一步的反向引用在输入名称和它的名称之间交替价值

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

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

【问题讨论】:

  • 这并不臃肿 :) 你应该看过我的一些 apache 配置。说真的,4 条重写规则行是完全合理的。
  • 这只是我的配置的一部分,我觉得我可以改进但不知道如何改进,我目前正在处理其他部分;)

标签: regex apache mod-rewrite


【解决方案1】:

喜欢 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++;
    }
}

【讨论】:

  • 不完全是我想要的,但仍然是一个不错的选择
  • 以后在脚本中如何处理?
  • 如果我们使用input_filter() with INPUT_GET这个方法呢?我们无法过滤它们。
【解决方案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' 的数组

【讨论】:

  • 没有按预期工作,因为 $_SERVER['REQUEST_FILENAME'] 应该是 $_SERVER['REQUEST_URI'] 并且 $mode 始终为空。原则是好的。
【解决方案3】:

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

您的 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 对的数量没有限制。

【讨论】:

  • 感谢您的评论。它肯定有助于另一个问题(不是关于 SO)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-08
  • 1970-01-01
  • 1970-01-01
  • 2015-12-20
  • 2011-03-12
相关资源
最近更新 更多