Appache: Hiding file extension from browser address bar

Hi all,

I’ve managed to implement the below code within the .htaccess file to allow displaying PHP files without the .php file extension, i.e. http://www.<site domain>/example instead of http://www.<site domain>/example.php.

# Remove PHP extension from links
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\\.php -f
RewriteRule ^(.*)$ $1.php

This works fine.

The problem is all the links within each of the website’s pages are set to link with the .php file extension. For this reason a browser’s address bar will display http://www.<site domain>/example.php instead of http://www.<site domain>/example

How can I (via htaccess) force browsers to display http://www.<site domain>/example even though the links are set to http://www.<site domain>/example.php?

I could of course go redoing all the links in each of the pages (the long winded way) though I suspect htaccess can do this via a rewrite rule?

As always, many thanks,

I guess I spoke too soon, the above code works fine providing I test the website on localhost, once I upload the modified htaccess file it won’t work online (no errors, just won’t display any page unless it ends with .php).

I’ve managed to work it out…but (there’s always a but isn’t there?) it won’t work online, only on localhost. The below removes displaying the .php from the browser’s address bar just fine (on localhost):

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

RewriteCond %{THE_REQUEST} [1]{3,9}\ /([^.]+\.)+php\ HTTP
RewriteRule ^(.+)\.php$ /$1 [R=301,L]

Why won’t it work online? It trims the .php all okay but basically gives me a 404 suggesting it’s not completing the rewrite fully? I need to insert the URI/URL in there somewhere?

If any of you are Apache gurus with sharp eyes I would appreciate your suggestions.

Thanks,


  1. A-Z ↩︎

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

RewriteCond %{THE_REQUEST} [1]{3,9}\ /([^.]+\.)+php\ HTTP
RewriteRule ^(.+)\.php$ /$1 [R=301,L]

I believe the reason it works on localhost but not online is the line in red…


  1. A-Z ↩︎

I got it to work with the host via:

Options -MultiViews

# Remove PHP extension from links (internally)
RewriteCond &#37;{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ /$1.php [L,QSA]
# Remove PHP extension from links (externally)
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\\ /([^.]+\\.)+php\\ HTTP
RewriteRule ^(.+)\\.php$ /$1 [R=301,L]

Works super dupa except…another but (when does it stop?)…I can no longer pass variables from my contact.php form (where the form is) to my sendemail.php(the form processing code) using the POST method.

I.e. $_POST[‘name’] is now null, regardless what value gets typed in the form field.

As soon as I remove the above Apache lines, upload htaccess the contact.php and sendemail.php work 100% fine.

Somehow, the above Apache code is interfering with the PHP $_POST method.

2 options I see:
a) Fix the above Apache code to not interfere
b) Add additional Apache code to not process sendemail.php in an extensionless format

Oh boy, my hunt on Google continues.

That’s because you redirect from every .php file to its non-.php equivalent using an external redirect. So when you post to sendmail.php, Apache redirects to /sendmail and the $_POST data is gone. poof

Why don’t you change the links in the HTML output from /something.php to /something btw? Or are there too many links to make that feasible?

Thank you so much for writing the below in bold:

That’s because you redirect from every .php file to its non-.php equivalent using an external redirect. So when you post to sendmail.php, Apache redirects to /sendmail and the $_POST data is gone. poof

I’m not sure if you explicitly or implicitly stated me to do as I did in your further text but the above text in bold gave me an immediate idea to go into contact.php and change action=“sendemail.php” to action=“sendemail”…and guess what? It works right on, each and every time. :slight_smile: :slight_smile: :slight_smile: It’s such a relief to get this back on track.

What’s the verdict? It would seem at least the PHP garbage collector is working very well, cleaning up void variables in real time.

Thanks again.

Good to see you figured it out!
My question still stands though: why don’t you change all links in the HTML output to the non-.php versions?
Right now you’re letting Apache and the browser of your visitor do a lot of work (redirecting) you could easily avoid by simply changing the links in your code.
Of course I were you I would still leave the .php -> non-.php rewrite for Search Engines and other links to your website that still point to the .php version, but linking all to .php and then redirect to non-.php seems a bit superfluous to me.

My question still stands though: why don’t you change all links in the HTML output to the non-.php versions?

Hmm, I guess the best answer to this is that the website has many pages, each has various links and so the process of manually changing all the links from .php to just extensionless is a spot tedious.

That would be nice, but I was rather thinking of doing it via PHP preg_replace(). I could do this but I can’t run it before the page finishes being rendered since if I do it in real-time it will destroy all my PHP include/include_once/require lines of codes etc. thus cause the page not to load at all (white screen).

Another reason why I agree it would be best to remove .php links from inside the code is security, hacker’s will be less delighted to see file extensions removed.

Just a case of automating it, it’s too late to do it manually without a) a lot of effort and b) potentially missing something thus causing additional debugging time before its all spanking clean and flaw free.