apache mod_rewrite一个规则适用于任意数量的可能性

时间:2022-11-24 08:21:43

I'm building a fairly large website and my .htaccess is starting to feel a bit bloated, is there a way of replacing my current system of - one rule for each of the possibile number of vars that could be passed, to one catch all expression that can account for varying numbers of inputs ?

我建立一个相当大的网站,. htaccess开始有点臃肿,有一种替代我现在的系统——一个规则为每个相信能通过var的数量,一个捕获所有表达式可以解释不同数量的输入?

for example I currently have:

例如,我目前有:

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

the first backreference is always the mode and (if any more exist) the second is always id, thereafter any further backreferences alternate between the name of the input and its value

第一个回引用始终是模式,第二个(如果存在的话)始终是id,此后任何进一步的回引用都在输入的名称和它的值之间交替出现

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

I would love to be able to have one expression to gracefully handle all the inputs.

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

3 个解决方案

#1


8  

Do like Drupal:

做像Drupal:

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

And then handle all the stuff in your script using php code something like this

然后用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


7  

I don't know if it can be done with a single expression, but it can be done with a fixed number of expressions, no matter how long the query string.

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

Your mod_rewrite rules will be called repeatedly, giving you what is sometimes called mod_rewrite recursion. There are techniques for avoiding it, but I think you want to use it.

您的mod_rewrite规则会被反复调用,有时会用到mod_rewrite。有一些技巧可以避免它,但我认为你想用它。

Set up a rule that replaces the last pair with name=value&

设置一个规则,用name=value&替换最后一对

Keep tacking on the input query string to the output. Every time through, your query string will get longer and your URL will get shorter.

继续向输出添加输入查询字符串。每次通过,你的查询字符串会变长,你的URL会变短。

Eventually you have only a single value that matches your last rule.

最终,您只有一个与最后一条规则匹配的值。

You have to capture the query string with

您必须使用

RewriteCond %{QUERY_STRING} ^(.*)$

And then you add it back to the output with %1

然后用%1将它添加回输出

You'd end up with four lines.

你会得到四行。

I know four lines is what you started with, but you'd match as many parameters as you want without having to add a fifth line.

我知道你一开始有四行,但是你可以匹配任意多的参数,而不需要添加第五行。

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

This will rewrite the following

这将重写以下内容。

/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.

当只剩下一个参数时,它停止。它将使用第一个“参数”并使用该名称调用.php文件。param/val对的数量没有限制。

#3


2  

I don't believe that their is a way - but I'd say that your best bet would be to have the script "index.php" process a path instead of having to do so many back references.

我不相信这是一种方法——但我得说,你最好的选择是拥有剧本“索引”。php“处理路径,而不需要做那么多反向引用。

So for example, your rewriterule would be

例如,rewriterule

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

Or similar... This would then make the $_SERVER['REQUEST_URI'] variable contain the path information, which you can split and parse.

或类似的…这将使$_SERVER['REQUEST_URI']变量包含路径信息,您可以对其进行分割和解析。

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

This ends up with $mode containing the mode, and $path containing an array of elements that are the rest of your path, so

最后是包含模式的$mode,以及包含作为路径其余部分的元素数组的$path

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

Would leave you with $mode being 'foo' and $path being an array containing 'bar' and 'baz'

$mode的意思是foo, $path的意思是包含bar和baz的数组

#1


8  

Do like Drupal:

做像Drupal:

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

And then handle all the stuff in your script using php code something like this

然后用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


7  

I don't know if it can be done with a single expression, but it can be done with a fixed number of expressions, no matter how long the query string.

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

Your mod_rewrite rules will be called repeatedly, giving you what is sometimes called mod_rewrite recursion. There are techniques for avoiding it, but I think you want to use it.

您的mod_rewrite规则会被反复调用,有时会用到mod_rewrite。有一些技巧可以避免它,但我认为你想用它。

Set up a rule that replaces the last pair with name=value&

设置一个规则,用name=value&替换最后一对

Keep tacking on the input query string to the output. Every time through, your query string will get longer and your URL will get shorter.

继续向输出添加输入查询字符串。每次通过,你的查询字符串会变长,你的URL会变短。

Eventually you have only a single value that matches your last rule.

最终,您只有一个与最后一条规则匹配的值。

You have to capture the query string with

您必须使用

RewriteCond %{QUERY_STRING} ^(.*)$

And then you add it back to the output with %1

然后用%1将它添加回输出

You'd end up with four lines.

你会得到四行。

I know four lines is what you started with, but you'd match as many parameters as you want without having to add a fifth line.

我知道你一开始有四行,但是你可以匹配任意多的参数,而不需要添加第五行。

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

This will rewrite the following

这将重写以下内容。

/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.

当只剩下一个参数时,它停止。它将使用第一个“参数”并使用该名称调用.php文件。param/val对的数量没有限制。

#3


2  

I don't believe that their is a way - but I'd say that your best bet would be to have the script "index.php" process a path instead of having to do so many back references.

我不相信这是一种方法——但我得说,你最好的选择是拥有剧本“索引”。php“处理路径,而不需要做那么多反向引用。

So for example, your rewriterule would be

例如,rewriterule

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

Or similar... This would then make the $_SERVER['REQUEST_URI'] variable contain the path information, which you can split and parse.

或类似的…这将使$_SERVER['REQUEST_URI']变量包含路径信息,您可以对其进行分割和解析。

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

This ends up with $mode containing the mode, and $path containing an array of elements that are the rest of your path, so

最后是包含模式的$mode,以及包含作为路径其余部分的元素数组的$path

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

Would leave you with $mode being 'foo' and $path being an array containing 'bar' and 'baz'

$mode的意思是foo, $path的意思是包含bar和baz的数组