How to RewriteRule if file exists elsewhere
I have been trying to accomplish the same as many frameworks do: having the request processed by a .php (namely, index.php), while keeping a /application/public
folder which contains all the elements that should be shown in case they exist. For example:
folder /application/public
total 28K
92897619 drwxr-xr-x 5 1001 1001 4.0K Jul 29 00:07 .
92897616 drwxr-xr-x 7 1001 1001 4.0K Jul 28 23:31 ..
92897754 -rw-r--r-- 1 1001 1001 15 Jul 29 00:07 .htaccess
92897733 drwxr-xr-x 2 1001 1001 4.0K Jul 28 23:31 images
92897620 -rw-r--r-- 1 1001 1001 696 Jul 28 23:58 index.php
92897625 drwxr-xr-x 2 1001 1001 4.0K Jul 28 23:31 javascript
92897734 drwxr-xr-x 2 1001 1001 4.0K Jul 28 23:31 stylesheets
folder /:
total 24K
92831996 drwxr-xr-x 4 1001 1001 4.0K Jul 29 02:44 .
91980897 drwxr-xr-x 5 0 0 4.0K Jul 6 00:30 ..
92831975 -rw-r--r-- 1 1001 1001 360 Jul 29 02:44 .htaccess
92897616 drwxr-xr-x 7 1001 1001 4.0K Jul 28 23:31 application
92832733 -rw-r--r-- 1 1001 1001 696 Jul 29 00:02 index.php
92897739 drwxr-xr-x 6 1001 1001 4.0K Jul 28 23:31 system
If there is a request for example.com/images/a.jpg
, /application/public/images/a.jpg
should be shown, as it exists. Otherwise, index.php would get ?uri=images/a.jpg
as query string.
With this in mind, I wrote the following .htaccess (placed at /):
Options +FollowSymLinks +Indexes
RewriteEngine on
RewriteBase /
RewriteCond %{DOCUMENT_ROOT}/application/public%{REQUEST_URI} -f
RewriteCond %{DOCUMENT_ROOT}/application/public%{REQUEST_URI} -d
RewriteRule ^(.*)?$ application/public/$1 [L]
RewriteRule ^(.+)?$ index.php?uri=$1 [PT,QSA,L]
Still, requesting for anything existent at /application/public
redirects the request to index.php
(for example, example.com/images/a.jpg
ends up being example.com/index.php?uri=images/a.jpg
).
Apache logs only show the following (when requesting example.com/javascript/index.php
):
File does not exist: /home/jbayardo/www/test/javascript
This, as you can imagine, leaves me in the blank.
Add
[OR]
at the end of first RewriteCond line.Currently the logic is
AND
: currently it reads as "if it is a file that exists AND if it is a folder that exists" .. which cannot be true -- conditions are not satisfied and rewrite does not occur.You need "if it is a file that exists OR if it is a folder that exists".
See docs: http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritecond (you have to scroll down a bit).
Even if rule #1 will work properly, it will still end up rewritten to
index.php?uri=$1
-- because that what you are telling Apache to do. You need to add a condition to prevent rewriting already rewritten URLs (keep in mind, that when Apache rewrites URL, it goes to next iteration ans start matching all rules again from top -- that is how it works).The
?
in RewriteRule patterns are not needed.
This is how I see it:
Options +FollowSymLinks +Indexes
RewriteEngine on
RewriteBase /
RewriteCond %{DOCUMENT_ROOT}/application/public%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}/application/public%{REQUEST_URI} -d
RewriteRule ^(.+)$ application/public/$1 [L]
RewriteCond %{REQUEST_URI} !^/(application/public/|index.php)
RewriteRule ^(.*)$ index.php?uri=$1 [PT,QSA,L]
精彩评论