I want to rewrite all my URLs to hide the .php
extension. A general rule that adds .php
to all URLs obviously won't do, so I want this rule to be conditional on the fact that
- There is no file nor directory that matches the URL
- After adding the
.php
, there is a match
I've arrived at these rewriting rules:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [L]
The first two take care of checking whether the request can be satisfied without rewriting (so for images and other non-PHP content). With the third rule I'd like to check if adding .php
would make the request valid (if not, we'll try something else further down the rewrite rules, or return 404).
The RewriteCond %{REQUEST_FILENAME}.php -f
part never seems to match though. Any suggestions?
EDIT
The rewrite log is containing these entries:
(4) RewriteCond: input='/contact' pattern='!-f' => matched
(4) RewriteCond: input='/contact' pattern='!-d' => matched
(4) RewriteCond: input='/contact.php' pattern='-f' => not-matched
I find it strange that it's trying to match /contact, and not /var/www/mysite/htdocs/contact (At least that's what I'd expect when reading the docs on REQUEST_FILENAME
). Apparently REQUEST_FILENAME
is only what I expect when there is an actual match?
EDIT2
Thanks to Thomas for the answer: use %{DOCUMENT_ROOT}
instead to manually compose the complete filename of the as yet unfound PHP file.
I've also thrown in an extra '/?' in the regexp to remove an optional / at the end of the URL, now all of /contact, /contact/ and /contact.php all refer to /contact.php:
RewriteCond %{DOCUMENT_ROOT}$1 !-f
RewriteCond %{DOCUMENT_ROOT}$1 !-d
RewriteCond %{DOCUMENT_ROOT}$1\.php -f
RewriteRule ^(.*?)/?$ $1.php [L]
UPDATE
After a lot of cursing I also found out that it depends on whether the RewriteRules are inside a <Directory> directive or .htaccess file on the one hand, or in your <VirtualHost> directive or just in the main body of an httpd.conf on the other hand. When inside a <Directory>/.htaccess, %{REQUEST_FILENAME}
does contain the path so my initial solution should work there. Outside of <Directory>, you need to add the %{DOCUMENT_ROOT}
yourself.