0

At the moment, I have a simple .htaccess that tidies up my page urls, by knocking the .php off the end, or adding it, depending on which way you look at it.

Basically, /about.php will become /about.

However, this results in my page being accessible on both of those urls. I can just suck it up and use rel=canonical tags but I'd also like to tidy it in my htaccess.

Is there a better way (clever rule) to 301 the .php to the none .php version, other than manually specifying each url?

Also, do I really need those rewritecond rules?

<IfModule mod_rewrite.c>


RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ /$1.php [QSA,L]


ErrorDocument 404 /404


</IfModule>
Chris J Allen
  • 18,970
  • 20
  • 76
  • 114

2 Answers2

0

To redirect (301) each .php-URL to the non-.php version (in case it's an existing file) you could use this one:

RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{THE_REQUEST} \.php\ HTTP/.\..$
RewriteRule ^(.*)\.php$ /$1 [QSA,R=301,L]

The first two RewriteCond in your .haccess are not really required, because you will have some conflicts anyway, e.g. if you have a file foo.htm and foo.htm.php, which one should be shown when foo.htm is requested?

So the complete mod_rewrite block:

RewriteEngine On
# redirect /foo.php to /foo
 RewriteCond %{REQUEST_FILENAME} -f
 RewriteCond %{THE_REQUEST} \.php\ HTTP/.\..$
 RewriteRule ^(.*)\.php$ /$1 [QSA,R=301,L]
# rewrite /foo to /foo.php
 RewriteCond %{REQUEST_FILENAME}.php -f
 RewriteRule ^(.*)$ /$1.php [QSA,L]
Floern
  • 33,559
  • 24
  • 104
  • 119
  • See my answer. I'll also improve my other post on URL rewriting how-to. It does only states this implicitly. – M'vy Jun 29 '11 at 13:25
0

In you original rules, you are just saying that any page that is not a file or a directory has to be redirected to the same name with .php appended.

So what you need to do to "remove" access to the .php file is to mask it with a redirection. So you will tell the client browser that foo/foo.php is in fact foo/foo.

This will trigger a new request to foo/foo by the client.

Then you tell the server that foo/foo is in fact foo/foo.php. This will trigger an internal request to foo/foo.php. So here you have a loop. We need to avoid that. The best workaround I've found is to check wethere the %{REDIRECT_URL} is empty or not.

Finally rules are :

# External redirection from real file to virtual with safe guard for internal redirection.
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REDIRECT_URL} !^$ 
RewriteRule ^(.*)\.php$ /$1 [QSA,R=301,L]

# Internal redirection to real file.
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ /$1.php [QSA,L]

Do not forget that ANY rewrite/redirection triggers a new request!

See : How does url rewrite works?

Community
  • 1
  • 1
M'vy
  • 5,696
  • 2
  • 30
  • 43
  • hmmm. Annoying. Working for me... Need to lurk moar on this issue. – M'vy Jun 29 '11 at 13:46
  • Well the try to add `E=REDIRECT_URL:$1` to the last RewriteRule flags? – M'vy Jun 29 '11 at 13:48
  • I found a solution: check `%{THE_REQUEST}` for `.php`. (`%{REQUEST_URI}` doesn't work too..) – Floern Jun 29 '11 at 13:50
  • In fact, why would people ask for `.php` files? If all the links on the page are without suffixe, then they'll never be called. By the way, what would be the problem if someone once call a `.php` file anyway. – M'vy Jun 29 '11 at 14:18