From RewriteCond
REQUEST_FILENAME
The full path of the local file system to the file or script corresponding to the request, if it was already determined by the server at the time of the REQUEST_FILENAME link. Otherwise, for example, when used in the context of a virtual host, the same value as REQUEST_URI. Depending on the value of AcceptPathInfo, the server can use only some of the leading REQUEST_URI components to match the request with the file.
and $_SERVER
'SCRIPT_FILENAME'
The absolute name of the current executable script.
It will be the same (full path to the script) if REQUEST_URI actually matches the existing file.
If it is not, REQUEST_FILENAME will simply be REQUEST_URI , and SCRIPT_FILENAME will be the name of the executable file of the PHP script. $_SERVER['REQUEST_URI'] will be REQUEST_FILENAME (aka REQUEST_URI ).
In your case, SCRIPT_FILENAME will always be /path/to/index.php , and REQUEST_FILENAME / REQUEST_URI will be available through $_SERVER['REQUEST_URI'] .
Update
REQUEST_URI will never be a file name because it lacks the root prefix of the document. When you use
RewriteCond %{REQUEST_URI} !-f
the condition will always be true, even if the requested URL matches an existing file. The next RewriteRule will always be executed, although it should call another PHP script or serve HTML, CSS or an image file.
Update
To answer the question.
But why is this value not available in PHP?
REQUEST_FILENAME not available in PHP because it is not in the environment or in the request headers.
All you can see in PHP is either an environment variable, or in the headers, or something that PHP can do. Since PHP does not try or cannot establish a connection between the request URI and some file name, you cannot access it anywhere. REQUEST_FILENAME can be anywhere on the file system.
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'] .