If file in public folder not exist connect to index.php
.
/localhost/project/
show index.php
/localhost/project/wrongpath
show /public/index.php
/localhost/project/js/main.js
show /public/js/main.js
htdocs
| project
| | public
| | | index.php
| | | js
| | | | main.js
| | | image
| | | | def.png
| | | css
| | | | main.css
| | | asset
So, basically, you want to implement a front-controller pattern, but the public
directory is "hidden" from the (visible) URL.
You should use 2 .htaccess
files. The first in the /project
subdirectory simply rewrites all requests to the /project/public
subdirectory. And the second in the /project/public
subdirectory that implements the front-controller pattern, rewriting requests to index.php
.
For example, the first .htaccess
file:
# /project/.htaccess
RewriteEngine On
# Rewrite all requests to the public subdirectory
RewriteRule (.*) public/$1 [L]
And the second .htaccess
file:
# /project/public/.htaccess
DirectoryIndex index.php
RewriteEngine On
# Front-controller pattern
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [END]
The presence of the second .htaccess
file in the public
subdirectory also acts to prevent a rewrite loop when the first .htaccess
file rewrites the request to the subdirectory, since mod_rewrite directives are not inherited by default.
Note the absence of any RewriteBase
directive and the use of relative URL-paths in the substitution string (2nd argument to the RewriteRule
directive).
The use of the END
flag on the last rule assumes you are on Apache 2.4.
With the above .htaccess
files:
A request for /project/
is internally rewritten to /project/public/
by the first .htaccess
file. mod_dir then serves the directory index (index.php
) from that directory.
/project/wrongpath
is rewritten to /project/public/wrongpath
by the first .htaccess
file. mod_rewrite then serves /project/public/index.php
since wrongpath
does not map to a physical file or directory.
/project/js/main.js
is rewritten to /project/public/js/main.js
by the first .htaccess
file. Since this now maps to a physical file, the first condition (RewriteCond
directive) fails and no additional rewrite occurs. The file is served directly.