我们有以下重写规则:
RewriteRule ^([A-Za-z0-9_]+)$ index.php?rewrite=$1 [L,QSA]
我们想知道是否有办法?rewrite=$1是否优先于通过请求uri中的查询字符串传递的值?
因为目前的情况是,由于QSA标志(我们确实需要btw),如果命中以下url:
http://www.domain.com/this_rewrite_will_match_the_above_rule?rewrite=some_value
PHP中$_GET['write']的值将是some_value,而不是this_write_will_match_The_above规则。
在我们开始修改重写并添加RewriteCond以匹配查询字符串之前,等等……我们希望有一个标志可以设置,以便目标url(在这种情况下为index.php?rewrite=$1)优先于传递的查询字符串值。
希望这是有道理的。
谢谢。
有点粗糙的
RewriteRule ^([A-Za-z0-9_]+)$ index.php?%{QUERY_STRING}&rewrite=$1 [L]
这是因为在php中,第二个rewrite=...
会覆盖第一个。
我已经多次强烈地搜索了一些机制来覆盖Apache重写中的单个查询字符串参数,但看起来没有这样做的选择,即使是最新的Apache版本(在撰写本文时为2.4.3)。
但是,还有一种替代方法可以利用这样一个事实,即PHP查询字符串解析器只返回多个相同查询字符串参数中的最后一个。
示例:
http://www.domain.com/index.php?id=123&id=456
这将返回$_GET:中的以下单个(!)条目
array(1) {
["id"]=>
string(3) "456"
}
因此,只需在现有查询字符串的末尾添加任何重写参数(而无需在查询字符串中删除它们),就可以解决问题。重复参数的最后一次出现是使其进入$_GET数组的参数。
不幸的是,QSA开关不适合这种技术,因为它总是将原始参数附加到新查询字符串的末尾。没有一个开关可以预处理旧参数。因此,您必须使用RewriteCond来捕获并准备原始查询字符串,而不是使用QSA:
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^([A-Za-z0-9_]+)$ index.php?%1&rewrite=$1 [L]
RewriteCond的唯一功能是捕获%1中的查询字符串。条件的正则表达式(.*)
始终匹配,因此始终执行以下RewriteRule。
使用此技术,您的上述测试用例将重写为…
http://www.domain.com/index.php?rewrite=some_value&rewrite=this_rewrite_will_match_the_above_rule
它将由PHP查询字符串解析器解释为
$_GET["id"] => "this_rewrite_will_match_the_above_rule"
这就是你想要的。
请注意,只有当您从PHP的$_GET数组中获取查询字符串值时,这才会起作用。如果您自己解析$_SERVER["QUERY_STRING"]
的内容或使用任何其他编程语言,则它不一定有效。
我选择创建自己的答案,因为它比Jpsy和Gerben提供的示例稍微干净一些。
信用是应该信用的地方,他们的建议是我来到这里的原因,我只扩展了他们:
因此,我们的最终解决方案包括2条规则。
# check if querystring is not empty (this is the addition vs other answers)
RewriteCond %{QUERY_STRING} !^$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([A-Za-z0-9_]+)$ index.php?%{QUERY_STRING}&rewrite=$1 [L]
如果上述查询字符串失败(主要是查询字符串为空),则应用此规则。
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([A-Za-z0-9_]+)$ index.php?rewrite=$1 [L]
我选择这种双重规则设置的原因是,如果查询字符串为空,避免php服务器变量被"?&rewrite=…"污染。
感谢jpsy和gerben的帮助。
我使用了以下说明:
RewriteRule ([^?]*)?(.*) $1?$2 [N] (1)
RewriteCond %{QUERY_STRING} (.*?)&?(rewrite=[^&]+)&?(.*)
RewriteRule ^(.*)$ $1?%1&%3 [N] (2)
RewriteRule ^(.*)$ $1?domain=newValue [L,QSA] (3)
技巧是由前两个规则中的[N]标志完成的,它导致重写引擎来重新处理输出。
规则(1)简单地按原样重写url。我需要它,因为我使用mod_rewrite togheter和mod_proxy_ajp,并且在第一次迭代中,查询字符串没有从url中分离出来。执行第一行后,url保持不变,但引擎将从查询字符串中分离路径。
规则(2)迭代并从查询字符串中删除所有出现的参数"rewrite"。
规则(3)设置参数的新值,并附加从规则(2)所做的替换中幸存下来的查询字符串。