mod_rewrite prefix problem

Tag: apache , .htaccess , mod-rewrite , apache2 Author: woodqlinni Date: 2010-07-22

I'm having some difficulties with mod_rewrite. My directory structure (part of it) is:

index.php
.htaccess
app
  controllers
  models
  views
  ...
  public
    javascripts
    stylesheets
    foo
      bar

So, as you can see, all static files are in app/public. That's the reason I would like to route requests like:

http://www.example.com/images/logo.png => app/public/images/logo.png  
http://www.example.com/javascripts/app.js => app/public/javascripts/app.js  
http://www.example.com/uploads/blog/something => app/public/uploads/blog/something

If that file doesn't exist, then it should route to index.php, like:

http://www.example.com/news/show/42 => index.php 
(Because file app/public/news doens't exist)


So, this is my current .htaccess, but I think it can be done in more elegant way.

RewriteEngine on
RewriteRule (png|jpg|gif|bmp|ico)$ app/public/images/$1/$2.$3 [L]
RewriteRule ([^/.]+).js$ app/public/javascripts/$1.js [L]
RewriteRule ([^/.]+).css$ app/public/stylesheets/$1.css [L]
RewriteRule ^(.*)$   index.php    [NC,L,QSA]

Also, problem with this one is, it only handles images, javascripts and stylesheets, but not all other files.

I know there is:

RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d

But, I don't know how to route them with prefix "app/public/"? I tried:

RewriteCond app/public/%{SCRIPT_FILENAME} !-f
RewriteCond app/public/%{SCRIPT_FILENAME} !-d

But it doesn't work! I also tried using RewriteBase, but it didn't work out.

EDIT:
I'm using mod_expires, and I'd really like to automate requests like:

http://www.example.com/images/logo.42.png => app/public/images/logo.png  
http://www.example.com/javascripts/app.42.js => app/public/javascripts/app.js  

So, as you can see, I would like to have optional number between filename and extension, and that number should be ignored (it is only used for future expires).

Previously, I found:

RewriteRule ^(.*)\.(\d+)(_m_\d+)?\.([^\.]+)$ $1.$4 [QSA]  

But I don't really understand how it works and does it always work in my example (multiple extensions maybe)?

Thanks!

Best Answer

Try this instead:

/.htaccess

RewriteEngine on
RewriteRule    ^$ app/public/    [L]
RewriteRule    (.*) app/public/$1 [L]

/app/.htaccess

RewriteEngine on
RewriteRule    ^$ public/    [L]
RewriteRule    (.*) public/$1 [L]

/app/public/.htaccess

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

Finally, create an index.php in your /app/public/ and put a dispatcher here:

<pre>
<?php

function dispatch($action, $request) {

    echo 'action: ' . $action;
    echo "\nparameters: " ;
    print_r($request);
}

$fragments = explode('/', $_GET['url']);
dispatch($fragments[0], array_slice($fragments, 1));

?>
</pre>

Now say try accessing:

# these will go through php
/controller/action
/post/create
/post/delete/1

# these are static files
/stylesheets/
/foo/bar/myfile.txt

comments:

I get 500, and in rewrite log, it looks like he got in infinitive loop . But I don't see why, [L] should mean it's last, right ? Also, if I understood well, you are redirecting everything to app/public, right ? What about index.php part? Sorry if I understood wrong!
@mfolnovich Sorry, I didn't paste the rest of the files
hey, tnx for your answer. now, it seems to work for static files, but: 1. for empty path, it displays app/public 2. for real requests, it crashes and in log, it says: script '/var/www/projects/petasite/app/public/index.php' not found or unable to stat, I tried putting ../../index.php?url=$1, but it caused 500. EDIT: can't figure out how to put newlines in comments :S
@mfolnovich You need create an index.php in /app/public which acts as a dispatcher.
Hmm, any way to avoid other index.php? If not, I guess there isn't any other solution, so tnx a lot! :)