I've been browsing the symfony2 framework source. In the htaccess file for their example website, I found the %{REQUEST_URI}::$1
written as follows:
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
The comment above that rule explains
The following rewrites all other queries to the front controller. The condition ensures that if you are using Apache aliases to do mass virtual hosting, the base path will be prepended to allow proper resolution of the app.php file; it will work in non-aliased environments as well, providing a safe, one-size fits all solution.
However, that doesn't explain the ::$1
or ::\2
.
Are they backreferences? If not, what are they? What is their purpose?
I have encountered almost the same htaccess file in my Zend project, and here are my thoughts and hope it helps.
The htaccess file (located at the Zend project directory, same as index.php) says
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]
Suppose Zend is installed at http://mydomain.tld/zend (let's call it yourdomain later on)
and we are requesting yourdomain/mycontroller/myaction
Therefore %{REQUEST_URI}
will be /zend/mycontroller/myaction
.
Note that $1
, which is the pattern in the RewriteRule
directive in the htaccess context [1], "will initially be matched against the filesystem path, after removing the prefix that led the server to the current RewriteRule
(e.g. app1/index.html
or index.html
depending on where the directives are defined)".
Therefore $1
will be mycontroller/myaction
.
And %{REQUEST_URI}::$1
will be /zend/mycontroller/myaction::mycontroller/myaction
.
The above string will be matched against ^(/.+)(.+)::\2$
. Note that for the two capturing groups in round braces i.e., (/.+)(.+)
before ::
many combinations can match that. For example:
Group 1: /z
Group 2: end/mycontroller/myaction
or
Group 1: /zend/mycontroller/myactio
Group 2: n
and anything in between is a valid match. In fact, the most interesting one would be
Group 1: /zend/
Group 2: mycontroller/myaction
which (is the only case that) makes backreference \2
(after ::
) to the second group a match.
In this case, /zend/
will be stored in the environment variable BASE
which is what the first RewriteRule
does. The %1
refers to the first matched string in RewriteCond
which is /zend/
.
Looking at the second RewriteRule
, it is clear that why there is a need for this. As index.php
can only be found in /zend/index.php
, we need to add /zend/
in front of index.php
.
Here we assume to use the URL-path as Substitution for the second RewriteRule
directive. Refer to [1] and search for "A DocumentRoot-relative path to the resource to be served" under the RewriteRule Directive section.
All the above leave the query string unchanged/untouched. It is up to index.php
how to parse the query string (as well as the URI).
Lastly goes the case where Zend is installed at the domain root.
%{REQUEST_URI}
will be /mycontroller/myaction
.$1
will be mycontroller/myaction
.The string to be matched by RewriteCond will be /mycontroller/myaction::mycontroller/myaction
.
This time the second group in (/.+)(.+)
will never match mycontroller/myaction
as there needs to be at least one letter following the initial backslash for the first group, making the second group as close as ycontroller/myaction
but not exactly mycontroller/myaction
so there cannot be a match.
As a result, the first RewriteRule
is not used. The BASE
enviornment variable will not be set, and when the second RewriteRule uses it, it will simply be empty.
References
[1] http://httpd.apache.org/docs/current/mod/mod_rewrite.html
The $1
in %{REQUEST_URI}::$1
references the matched string of the RewriteRule
directive, i.e., the matched string of .*
in ^(.*)
. So %{REQUEST_URI}::$1
is expanded to the requested URI path as supplied by the user, and the current internal URI path and query, separated by ::
.
The pattern ^(/.+)(.+)::\2$
is used to find a prefix (first capturing group) which makes the remaining part match the part behind the ::
(\2
is a back reference to the matched string of the second capturing group of the pattern).
If such a match is found, the prefix is stored in the environment variable BASE
([E=BASE:%1]
, where %1
references the matched string of the previous successful RewriteCond
pattern match).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With