views:

91

answers:

4

I just wanted to do a simple thing with mod_rewrite. I have a site which uses .php files, and I wanted to rewrite those to cleaner URLs, and remove the .php. So, files would be www.mysite.com/contact and so on.

This does work how I wanted, but I had expected that it would still serve my contact.php file, but just show the user that they were at /contact rather than contact.php. But, it is looking for a file just called contact, which, is not there.

So, what so I need to do, do still use my contact.php file, but rewrite the URL for the user to /contact ?

Here is what I am using:

SetEnv APPLICATION_ENV development
RewriteEngine on
RewriteBase /

# Always use www.
RewriteCond %{HTTP_HOST} ^mysite\.com$ [NC]
RewriteRule ^(.*)$ http://www.mysite.com/$1 [L,R=301]

# Change urlpath.php to urlpath
RewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]
RewriteRule ^(.*)\.php$ http://www.mysite.com/$1 [L,R=301]
+1  A: 

Your third rule should be the other way around:

# Change urlpath.php to urlpath
RewriteCond %{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

Sundeep
Only issue with this, is that it also rewrites images, css ect with a .php extension.
Nic Hubbard
A: 

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.

Fozi
A: 

Do

# Change urlpath.php to urlpath
RewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !\.php$ [NC]
Pez Cuckow
+4  A: 

For this solution, I have followed the following rules:

  1. If the user tries to load /something.php they should be externally redirected to /something.
  2. If the user tries to load /something then they should be internally redirected to /something.php.
  3. If the user passed any query string parameters to the URL then these should be preserved through the redirects.
  4. 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 on
RewriteBase /

## 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 domain
RewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]
## Don't perform this rule if we've already been redirected internally
RewriteCond %{QUERY_STRING} !internal=1 [NC]
## Redirect the user externally to the non PHP URL
RewriteRule ^(.*)\.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 domain
RewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]
## Perform this rule only if a file with this name does not exist
RewriteCond %{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 page
RewriteCond %{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]
NeilCrosby
The one problem with this one is that when going to www.mysite.com it won't pick up the index.php file. What do we need to add to this rule to make sure that it will be index files in a directory?
Nic Hubbard
Nice catch. I've added a `RewriteCond` to the final block to not run the `RewriteRule` if we're requesting the index page.
NeilCrosby
The right way to append a query parameter is to use the QSA flag.
Fozi
Thanks Fozi - I've ammended the final `RewriteRule` to use the QSA flag.
NeilCrosby