Redirect all to index.php using htaccess

David Ericsson picture David Ericsson · Aug 23, 2013 · Viewed 319.1k times · Source

I am writing a simple PHP-based MVC-ish framework. I want this framework to be able to be installed in any directory.

My PHP script grabs the request uri and breaks it off into segments. It makes segment 1 the controller and segment 2 the action. This goes all fine when I do this:

http://www.example.com/mvc/module/test/

It will go to the specific module controller and method. Now I have a default controller, the home controller, which is in folder home.

Now when I access this folder directly http://www.example.com/mvc/home/ It will display a 403 forbidden , because this folder does exist, instead it should also go back to http://www.example.com/mvc/index.php

If I would have installed the framework in a different folder, lets say folder framework it has to redirect back to http://www.example.com/framework/index.php

I would like to redirect every folder and php file back to the index.php, leaving everything else the way it is.

My first problem I encountered was it never redirects to the right folder, always to the domain root folder.

This is what I tried :

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]

Answer

CD001 picture CD001 · Aug 23, 2013

Your rewrite rule looks almost ok.

First make sure that your .htaccess file is in your document root (the same place as index.php) or it'll only affect the sub-folder it's in (and any sub-folders within that - recursively).

Next make a slight change to your rule so it looks something like:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]

At the moment you're just matching on . which is one instance of any character, you need at least .* to match any number of instances of any character.

The $_GET['path'] variable will contain the fake directory structure, so /mvc/module/test for instance, which you can then use in index.php to determine the Controller and actions you want to perform.


If you want the whole shebang installed in a sub-directory, such as /mvc/ or /framework/ the least complicated way to do it is to change the rewrite rule slightly to take that into account.

RewriteRule ^(.*)$ /mvc/index.php?path=$1 [NC,L,QSA]

And ensure that your index.php is in that folder whilst the .htaccess file is in the document root.


Alternative to $_GET['path'] (updated Feb '18 and Jan '19)

It's not actually necessary (nor even common now) to set the path as a $_GET variable, many frameworks will rely on $_SERVER['REQUEST_URI'] to retrieve the same information - normally to determine which Controller to use - but the principle is exactly the same.

This does simplify the RewriteRule slightly as you don't need to create the path parameter (which means the OP's original RewriteRule will now work):

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]

However, the rule about installing in a sub-directory still applies, e.g.

RewriteRule ^.*$ /mvc/index.php [L,QSA]



The flags:

NC = No Case (not case sensitive, not really necessary since there are no characters in the pattern)

L = Last (it'll stop rewriting at after this Rewrite so make sure it's the last thing in your list of rewrites)

QSA = Query String Append, just in case you've got something like ?like=penguins on the end which you want to keep and pass to index.php.