2

First of all, I know there are plenty of similar questions about this around, but

  1. None of them seem to work for me
  2. None of them actually address exactly what I want

What I want is, as the title suggests, to redirect URLs without the .php extension to the actual .php file - changing the URL if possible (which I presume is just handled by [R=301]). The latest thing I tried was this:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ $1.php [R=301]

That doesn't work. I can still cant access /about.php with /about. (.htaccess rules themselves are working fine though)

I understand RegEx fine, but htaccess rules just mess with my head =[

So what should I do?


Now I know what you're thinking

One of you will say this: "Why do you want to do this? Just get rid of extensions completely and access your pages via /about or /about/ with a trailing slash."

I'd like to do that, it looks quite good. Problem is SEO - from which I assume my page ranks will get annihilated because all of a sudden they're on different URLs. So before you suggest that, suggest how I'd keep my page ranks first.

What I'm actually doing is essentially URL shortening for a poster - it's a lot easier for people to remember mywebsite.com/about than mywebsite.com/about.php.

Chris Watts
  • 6,197
  • 7
  • 49
  • 98
  • Have you tried using the `L` flag in your rewrite rule? `RewriteRule ^(.*) $1.php [R=301,L]` – Cyclonecode May 04 '13 at 14:24
  • Wouldn't that prevent any other rules underneath it from being executed? I do have some more rules in my .htaccess. Just tried it, doesn't work anyway =[ – Chris Watts May 04 '13 at 14:35
  • I don't think you need the [R=301], just replace it with [L] as @KristerAndersson suggested since you're masking/mapping – Mi-Creativity May 04 '13 at 14:36
  • @CJxD - No, only when the above conditions are true. In cases where the conditions do not apply, the next condition(s)/rule(s) will be checked. – Cyclonecode May 04 '13 at 14:36
  • [L] by itself doesn't work. – Chris Watts May 04 '13 at 14:37
  • @CJxD I have this `RewriteRule ^(.*)$ $1.php [L]` and it is working. – Mi-Creativity May 04 '13 at 15:46
  • 1
    It's still not working! Why me!? I know mod_rewrite is definitely working from other RewriteRules I have - and I tried without these other rules and I still either get no effect, or a redirect loop - even after clearing my browser cache. – Chris Watts May 04 '13 at 23:39
  • @CJxD Do you mean, you have tried to use my code on the answer below, just itself without the other code in your [.htaccess - Pastebin.com](http://pastebin.com/cn57JFdw) while clearing your cache **or switching to different browser** to check it if it work? – 5ervant - techintel.github.io May 05 '13 at 17:20
  • 1
    @Servant Yes, I cleared all other Rewrite code and used just yours in the answer below. I even opened Internet Explorer. With your code, if I navigate to `/about/gallery`, then the 404 page shows. The URL in the address bar remains as `/about/gallery`. – Chris Watts May 06 '13 at 10:11

3 Answers3

1

Enable mod_rewrite and .htaccess through httpd.conf and then put this code in your .htaccess under DOCUMENT_ROOT directory:

Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /

## hide .php extension
# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R=302,L]

# To internally forward /dir/foo/ to /dir/foo.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.*?)/?$ $1.php [L]

Please Make sure you have MultiViews options disabled using: Options -MultiViews

Once you verify it is working fine, replace R=302 to R=301. Avoid using R=301 (Permanent Redirect) while testing your mod_rewrite rules.

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • This doesn't appear to work either - I get redirected to `/dir/foo`, but with a 404 error (and stylesheets break) – Chris Watts May 09 '13 at 09:57
  • Actually this is a working code from my web server. Can you post your latest .htaccess in your question and tell me which URI did you try for testing. Also for stylesheets, JS and images files make sure you are using absolute paths (starting with a slash or `http://`) – anubhava May 09 '13 at 10:12
  • Oh, the CSS issue will probably be down to the fact I have a PHP script that generates CSS for the specific browser. – Chris Watts May 10 '13 at 07:47
  • If PHP script is generating CSS script/file then you can easily alter to generate CSS with absolute path isn't it? – anubhava May 10 '13 at 08:55
  • Going to /style/css/cssgen.php will output the main stylesheet specific to your browser. So yeah, it's an absolute path - it just has the .php extension. – Chris Watts May 10 '13 at 09:23
  • It seems your `Options -MultiViews` has done the trick! Everything appears to suddenly be working! CSS outputs fine, but now I have another issue with a image resising script that goes along the lines of `/images/imageresiser.php?height=640&width=480&image=/images/pic.jpg` – Chris Watts May 10 '13 at 09:32
  • (The image URL can also contain spaces which are replaced with %20. It seems your rewrite script turns %20 into %2520) – Chris Watts May 10 '13 at 10:02
  • Solution to that is to use the `NE` flag on `RewriteRule ^ %1 [R=302,NE,L]` – Chris Watts May 10 '13 at 10:10
  • Right `NE` is for that purpose only. I recently posted a long answer on use of NE flag. When you get a chance pls check here: http://stackoverflow.com/questions/5279470/mod-rewrite-ne-flag-when-is-it-helpful-to-encode-special-chars-in-the-url/5588401#5588401 Glad that you resolved it :) – anubhava May 10 '13 at 12:12
  • For the purpose of helping out others who discover this thread, can you edit your answer to say "Make sure you have `-MultiViews`". I'll then award you the sweet sweet bounty =] – Chris Watts May 10 '13 at 13:12
  • One final thing - will I need to change all my links to point to `/about` instead of `/about.php` etc for SEO reasons, or will Google see past that without any issues? – Chris Watts May 11 '13 at 10:23
  • Please see this note in my answer `Once you verify it is working fine, replace R=302 to R=301. Avoid using R=301 (Permanent Redirect) while testing your mod_rewrite rules.` I suggest you to make it R=301 and then search engines wil automatically update their search results. Having said that IMO it is always better to update your links to point to `/about` instead of `/about.php` whenever time permits. – anubhava May 11 '13 at 20:29
  • 1
    I did change it to 301 - I understand the redirect codes. But yes, the correct answer is to update links otherwise you end up with more redirections than necessary, slowing the website response time down. – Chris Watts May 11 '13 at 23:58
0

Please make sure that there's mod_rewrite on your Apache HTTP Server and try this:

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_-]+)$ /$1.php [R]

But clear your cache or use another browser first before checking the redirecting dynamic URLs, because you've been previously used the [R=301] flag! For more info. about that, please visit: https://stackoverflow.com/a/15999177/2007055


Could you try this one but it's quite the same as the previous code:

RewriteEngine on

RewriteRule ^([a-zA-Z0-9_-]+)$ http://%{HTTP_HOST}/$1.php

And when it works, try adding these two conditions above the rewrite rule:

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_-]+)$ http://%{HTTP_HOST}/$1.php

And when any of these codes above does not work, I think there's a problem in your Apache HTTP Server.

Community
  • 1
  • 1
0

That works for me.

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

You can chain it if you want e.g.

RewriteEngine On

# Remove trailing slashes.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=permanent,QSA]

# Redirect to HTML
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+)$ $1.html [L,QSA]

# Redirect to PHP
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php [L,QSA]

# Redirect to ASP
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.asp -f
RewriteRule ^(.+)$ $1.asp [L,QSA]
Petr
  • 1