Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mod_rewrite to remove .php extension AND preserve GET parameters

I have looked at these solutions and none of them actually work properly on my end:

mod_rewrite to remove .php but still serve the .php file?

How to remove file extension from website address?

How to use Apache Mod_rewrite to remove php extension, while preserving the GET parameters?

and they just don't do the following, which is what I need done:

1) remove .php extension from files and instead of /index.php display /index

2) preserve GET parameters (which I read and store in session cookies while the file is being loaded, in the header), so instead of /index.php?a=1&b=2 display maybe /index/a1/b2

3) work on subdomains and https:// without messing up the URL completely or ending up in an infinite loop or something...

Does anyone have a clue how to put together these rules so they cover the 3 points above correctly?

This is what I'm working with as a starting point:

RewriteCond %{THE_REQUEST} (\.php(.*)\sHTTP/1)
RewriteRule ^(.+)\.php$ /$1 [R=301,L,QSA]
like image 661
Crazy Serb Avatar asked Apr 26 '13 06:04

Crazy Serb


People also ask

How do you hide a file extension on a website?

You can now link any page inside the HTML document without needing to add the extension of the page as no extension will be visible now in the URL of the website. The search engine may index these pages as duplicate content, to overcome this add a <canonical> meta tag in the HTML file.


2 Answers

You're seeing this the wrong way round. You don't want to redirect a request for a .php file to a clean address, because you never want the user to see the .php in the first place. Instead you need to take a request which does not end with .php and then check to see whether the file (underneath the surface) actually has a .php extension. Then, if that's the case, silently rewrite the request to add the .php extension, so that the user never needs to see the extension.

Try the following:

RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([a-zA-Z0-9_-]+)/?$ /$1.php [QSA]

The RewriteCond checks to see whether the request (tacked on to the end of the DOCUMENT_ROOT path) forms a valid filename once ".php" is added to the end of it. If so, then the RewriteRule is allowed to silently rewrite the request so that ".php" is added to the request path. The QSA flag tells mod_rewrite to append the existing query string to the end of the new request path, so your GET variables should be preserved.

Note that DOCUMENT_ROOT may or may not have a trailing slash already, so you might need to get rid of the slash before $1 in the RewriteCond.

As for query string parameters, mod_rewrite cannot handle an indefinite number of variables, so you would need to give an explicit request pattern in your question before a mod_rewrite solution could offer a way to map it to a query string.

like image 165
Bobulous Avatar answered Oct 08 '22 18:10

Bobulous


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 %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*?)/?$ $1.php [L]

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

like image 23
anubhava Avatar answered Oct 08 '22 18:10

anubhava