I'm trying to understand the following htaccess rule in more detail:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]
</IfModule>
Specifically, I'm trying to understand how REQUEST_FILENAME works. There are several resources which I've found discussing this, from the mod_rewrite docs to answers here on Stack Overflow. But none seem to be addressing exactly what I'm looking for which is how do I take a closer look at the REQUEST_FILENAME variable in order to see it's value?
Typically, when I want to look at a variable being referenced in .htaccess, I will use print_r to look at the $_SERVER global to see what the server things those values are:
echo "<pre>";
print_r($_SERVER);
echo "</pre>";
die('fin');
That can help me see values such as $_SERVER['REQUEST_URI'] above. But it doesn't seem that REQUEST_FILENAME is available in any of the PHP $GLOBALS in my current environment. I do see a value for SCRIPT_FILENAME, and several sources say that these two values are equal, but it's not clear if they are substitutes or if REQUEST_FILENAME falls back to SCRIPT_FILENAME if the first is not present.
I have been able to output the REQUEST_FILENAME value by updating the htaccess rule slightly to output the value in the URL, changing the last line to:
RewriteRule (.+) index.php?p=%{REQUEST_FILENAME} [R=302,QSA,L]
But why isn't this value available anywhere in PHP? Is there anything I'm overlooking that can help me understand where this variable is stored and how to view it's value via PHP?
From RewriteCond
REQUEST_FILENAME
The full local filesystem path to the file or script matching the request, if this has already been determined by the server at the time REQUEST_FILENAME is referenced. Otherwise, such as when used in virtual host context, the same value as REQUEST_URI. Depending on the value of AcceptPathInfo, the server may have only used some leading components of the REQUEST_URI to map the request to a file.
and from $_SERVER
'SCRIPT_FILENAME'
The absolute pathname of the currently executing script.
This will be the same (the full path to the script), if the REQUEST_URI
actually corresponds to an existing file.
If it doesn't, REQUEST_FILENAME
will be just REQUEST_URI
and SCRIPT_FILENAME
will be the name of the PHP script executing. $_SERVER['REQUEST_URI']
will beREQUEST_FILENAME
(aka REQUEST_URI
).
In your case, SCRIPT_FILENAME
will always be /path/to/index.php
and REQUEST_FILENAME
/REQUEST_URI
will be accessible through $_SERVER['REQUEST_URI']
.
Update:
REQUEST_URI
will never be a filename, because it lacks the document root prefix. When you use
RewriteCond %{REQUEST_URI} !-f
the condition will always be true, even when the requested URL would match an existing file. The following RewriteRule
will always be executed, although it should call another PHP script or serve a HTML, CSS or image file.
Update:
To actually answer the question.
But why isn't this value available anywhere in PHP?
REQUEST_FILENAME
isn't available in PHP, because it isn't in the environment or in the request's headers.
All you can see in PHP, is either some environment variable or in the headers or something PHP can deduce itself. Since PHP doesn't try or isn't able to make the connection between the request URI and some filename, you cannot access it anywhere. The REQUEST_FILENAME
might be anywhere in the filesystem after all.
You can, however, put it in the environment yourself
RewriteRule (.+) index.php?p=$1 [QSA,L,E=REQUEST_FILENAME:%{REQUEST_FILENAME}]
and access it in PHP as $_SERVER['REDIRECT_REQUEST_FILENAME']
.
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