9

我一直在浏览 symfony2 框架源码。在他们的示例网站的 htaccess 文件中,我发现%{REQUEST_URI}::$1写法如下:

RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*) - [E=BASE:%1]

该规则上方的评论解释了

以下将所有其他查询重写到前端控制器。该条件确保如果您使用 Apache 别名来进行大规模虚拟主机,则基本路径将被预先设置以允许正确解析 app.php 文件;它也可以在非混叠环境中工作,提供安全、一刀切的解决方案。

但是,这并不能解释::$1or ::\2

它们是反向引用吗?如果不是,它们是什么?他们的目的是什么?

4

2 回答 2

17

我在 Zend 项目中遇到了几乎相同的 htaccess 文件,这是我的想法,希望对您有所帮助。

htaccess 文件(位于 Zend 项目目录,与 index.php 相同)说

RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]

假设 Zend 安装在http://mydomain.tld/zend(我们稍后称它为 yourdomain)并且我们正在请求yourdomain/mycontroller/myaction

因此%{REQUEST_URI}/zend/mycontroller/myaction

请注意$1,这是RewriteRulehtaccess 上下文 [1] 中指令中的模式,“在删除将服务器引导到当前的前缀之后,最初将与文件系统路径匹配RewriteRule(例如app1/index.html,或index.html取决于指令的定义位置) ”。

因此$1mycontroller/myaction

并且%{REQUEST_URI}::$1/zend/mycontroller/myaction::mycontroller/myaction

上面的字符串将与^(/.+)(.+)::\2$. 请注意,对于圆括号中的两个捕获组,即(/.+)(.+)::许多组合可以匹配之前。例如:

第一组:/z

第 2 组:end/mycontroller/myaction

或者

第一组:/zend/mycontroller/myactio

第 2 组:n

介于两者之间的任何内容都是有效匹配。事实上,最有趣的应该是

第一组:/zend/

第 2 组:mycontroller/myaction

这(是唯一的情况)使对第二组的反向引用\2(之后)匹配。::

在这种情况下,/zend/将存储在BASE第一个RewriteRule所做的环境变量中。The%1指的是第一个匹配的字符串,RewriteCond其中 is /zend/

看第二个RewriteRule,很明显为什么需要这样做。由于index.php只能在 中找到/zend/index.php,我们需要/zend/在前面添加index.php

在这里,我们假设使用 URL 路径作为第二个RewriteRule指令的替换。请参阅 [1] 并在 RewriteRule Directive 部分下搜索“A DocumentRoot-relative path to the resource to beserved”。

以上所有内容都使查询字符串保持不变/不变。取决于index.php如何解析查询字符串(以及 URI)。

最后是 Zend 安装在域根目录的情况。

  • %{REQUEST_URI}/mycontroller/myaction
  • $1mycontroller/myaction

RewriteCond 要匹配的字符串将是/mycontroller/myaction::mycontroller/myaction.

这次第二组(/.+)(.+)永远不会匹配mycontroller/myaction,因为需要在第一组的初始反斜杠之后至少有一个字母,使第二组尽可能接近ycontroller/myaction但不完全mycontroller/myaction匹配,因此不可能匹配。

结果,第一个RewriteRule没有被使用。BASE环境变量不会被设置,当第二个 RewriteRule 使用它时,它会简单地为空。

参考

[1] http://httpd.apache.org/docs/current/mod/mod_rewrite.html

于 2013-09-03T09:49:22.163 回答
6

$1in%{REQUEST_URI}::$1引用RewriteRule指令的匹配字符串,即 in 的匹配.*字符串^(.*)。So%{REQUEST_URI}::$1扩展为用户提供的请求的 URI 路径,以及当前的内部 URI 路径和查询,用 . 分隔::

该模式^(/.+)(.+)::\2$用于查找前缀(第一个捕获组),该前缀使剩余部分与后面的部分匹配::\2是对模式的第二个捕获组的匹配字符串的反向引用)。

如果找到这样的匹配,则前缀存储在环境变量中BASE( [E=BASE:%1],其中%1引用了先前成功RewriteCond模式匹配的匹配字符串)。

于 2013-05-26T18:23:40.117 回答