mod_rewrite to remove .php but still serve the .php file?
For this solution, I have followed the following rules:
- If the user tries to load
/something.php
they should be externally redirected to/something
. - If the user tries to load
/something
then they should be internally redirected to/something.php
. - If the user passed any query string parameters to the URL then these should be preserved through the redirects.
- If the user tries to load a different file which really exists on the filesystem (a stylesheet, image etc) then this should be loaded as is.
And here's the final set of mod_rewrite magic:
RewriteEngine onRewriteBase /## Always use www.RewriteCond %{HTTP_HOST} ^mysite\.com$ [NC]RewriteRule ^(.*)$ http://www.mysite.com/$1 [L,R=301]# Change urlpath.php to urlpath## Only perform this rule if we're on the expected domainRewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]## Don't perform this rule if we've already been redirected internallyRewriteCond %{QUERY_STRING} !internal=1 [NC]## Redirect the user externally to the non PHP URLRewriteRule ^(.*)\.php$ $1 [L,R=301]# if the user requests /something we need to serve the php version if it exists## Only perform this rule if we're on the expected domainRewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]## Perform this rule only if a file with this name does not existRewriteCond %{REQUEST_FILENAME} !-f## Perform this rule if the requested file doesn't end with '.php'RewriteCond %{REQUEST_FILENAME} !\.php$ [NC]## Only perform this rule if we're not requesting the index pageRewriteCond %{REQUEST_URI} !^/$## Finally, rewrite the URL internally, passing through the user's query string## using the [qsa] flag along with an 'internal=1' identifier so that our first## RewriteRule knows we've already redirected once.RewriteRule ^(.*)$ $1.php?internal=1 [L, QSA]
Your third rule should be the other way around:
# Change urlpath.php to urlpathRewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]RewriteCond %{REQUEST_FILENAME} !\.php$ [NC]RewriteRule ^/?(.*)$ $1.php [L,R=301]
Once the user goes to /contact, it'll load contact.php. The extra RewriteCond is so that if people DO go to contact.php, it won't try to load contact.php.php
As I understand you want the URL to be /contact even if the URL was /contact.php.
You can check for the .php extension and do a redirect to remove it. Use R=301 (as you do).
Then you have to make your server accept the URL without the .php extension. It might actually already do that.
That's what mod_negotiation does. It should be installed by default, but you might have to enable it.
You can also do that with mod_rewrite, but remove the R from the options. It will redirect internally instead of answering with an HTTP redirect.