Welcome to WebmasterWorld Guest from

Forum Moderators: Ocean10000 & incrediBILL & phranque

Redirect all requests to public folder

MVC pattern

11:50 am on Aug 20, 2010 (gmt 0)

5+ Year Member

I'm having trouble writing the htaccess rewrite rules for an MVC pattern, so that all requests get redirected to a public folder.

http://www.example.com should go to http://www.example.com/public/index.php

http://www.example.com/mypage should go to

And requests for images, JS, CSS, etc. should be like:

http://www.example.com/css/stylesheet.css but really goes to http://www.example.com/public/css/stylesheet.css

Can someone please suggest appropriate rules for this? I'm getting infinite redirects mainly. Alternatively, I am interested to hear best practices on this kind of redirecting for MVC.
12:29 pm on Aug 20, 2010 (gmt 0)

WebmasterWorld Senior Member jdmorgan is a WebmasterWorld Top Contributor of All Time 10+ Year Member

What have you tried so far?

The only difficulty here is to exclude the target path "/public/" so that requests, once rewritten to that subdirectory, don't get rewritten again, causing a loop. A negative-match RewriteCond testing a back-reference to the RewriteRule pattern or %{REQUEST_URI} would do nicely.

Please post your best-effort code as a basis for discussion.

Also, to avoid confusion among our diverse readers, it would be helpful to know with some certainty what you mean by "MVC."

2:08 pm on Aug 20, 2010 (gmt 0)

5+ Year Member

Thanks JD.

Well the important parts of my application structure is as follows:

- application
------ config
------ controllers
------ models
------ views
- library
- public
------ css
------ img
------ js
------ index.php
- .htaccess file

All publically viewable files are stored in the /public/ directory, and only these files should be accessible through the browser. All requests for pages therefore need to get directed to /public/index.php?url=REQUEST_URI in the background (although the user doesn't see their URL change).

Obviously I need to include images, JS and CSS in my templates by http://www.example.com/img/picture.png, and another thing is that I need any original query string to be preserved and sent over to the rewritten URL as well.

Something like this?

RewriteCond %{REQUEST_URI} !public/
RewriteRule ^(.*)$ public/index.php?url=$1 [R,L]

But I don't know what to add as a RewriteCond really. If I go to the site, this is what I get (on shared hosting btw):


Not sure why it's writing the entire server path in.
6:24 pm on Aug 20, 2010 (gmt 0)

WebmasterWorld Senior Member jdmorgan is a WebmasterWorld Top Contributor of All Time 10+ Year Member

It is redirecting (asking the browser to change its address bar and make a new HTTP request) because you explicitly specified an external URL-to-URL redirect.

It is inserting the full filepath because a rule executed previous to this one has already rewritten the URL to a filepath, and you did not use an [L] flag on that rule. If you ever allow more than one rule to match a request, this is the result.

The rule itself should look like this:

# Internally rewrite all requested URLs to /public filepath unless already done
RewriteCond $1 !^public/
RewriteRule ^(.*)$ public/index.php?url=$1 [L]

You must insert this rule after all external redirect RewriteRules, and before any less-specific "catch-all" internal RewriteRules. You must not use mod_alias "Redirect" or "RedirectMatch" directives along with your RewriteRules -- if you use mod_rewrite for anything, use it for everything.

See the concurrent thread "Proper Order for htaccess [webmasterworld.com]", also in this forum for a lot more info on this subject. This will help you avoid some potentially-very-serious self-inflicted problems.

9:56 am on Aug 24, 2010 (gmt 0)

5+ Year Member

Ah, thank you so much. I really appreciate the help, and thanks for the link.
11:03 pm on Aug 25, 2010 (gmt 0)

5+ Year Member

OK, I have a follow-up question. I cannot get any of my CSS, JS or images to link in my HTML.

The paths in the HTML are like this:


But none of these links are being found. I need to modify the original rewrite so that requests for CSS/images/JS are simply forwarded to the public folder, but requests for anything else are rewritten to public/index.php?url=$1 as above.

9:13 am on Aug 26, 2010 (gmt 0)

5+ Year Member

OK, nevermind. Once again the mysterious htaccess caching problems I've been experiencing seem to have randomly made up their mind.

[webmasterworld.com ]
1:57 pm on Aug 26, 2010 (gmt 0)

WebmasterWorld Senior Member jdmorgan is a WebmasterWorld Top Contributor of All Time 10+ Year Member

I doubt that it was the caching problem making the code "not work." Rather, I think it's possible that the caching problem may be making the code appear to work, when in fact, it's still not right.

Exclude the paths you don't want rewritten to the script, either by directory-path or by filetype (this is your choice depending on which one will be easier for you to maintain).

# Internally rewrite all requested URLs to /public filepath unless already done
# Exclude by directory-path
RewriteCond $1 !^(public|images|css|js)/
# Exclude by filetype (optional)
RewriteCond $1 !\.(gif|jpe?g|png|bmp|ico|css|js)$
RewriteRule ^(.*)$ public/index.php?url=$1 [L]

9:15 am on Oct 5, 2010 (gmt 0)

5+ Year Member

Hi Jim,

On the last rule you posted, are you sure that will work? I have a feeling it might need two separate rules. If we use an example (and refer to the directory structure in the third post of this thread):


Should be rewritten to:


But for images, CSS, JS, etc:


Should be rewritten to:


Finally, I wanted to modify the original rule to keep any original query string parameters and add them to the rewritten one:


Should be rewritten to:


Is this possible?

Thanks in advance.
12:21 pm on Oct 5, 2010 (gmt 0)

WebmasterWorld Senior Member jdmorgan is a WebmasterWorld Top Contributor of All Time 10+ Year Member

Having figured out that you need two rules, it will likely be faster to code it up and test it than to ask here and wait for a response.

Rewrite the requests that need to be passed to your script first (with the rule discussed so far in this thread), then follow that rule with a more-general rule that rewrites "everything else" to insert the "/public" path, remembering to include the RewriteCond for "loop prevention."


Featured Threads

My Threads

Hot Threads This Week

Hot Threads This Month