Search code examples
apache.htaccessmod-rewrite

How to config .htaccess


If file in public folder not exist connect to index.php.

  1. /localhost/project/ show index.php
  2. /localhost/project/wrongpath show /public/index.php
  3. /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

Solution

  • 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:

    1. 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.

    2. /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.

    3. /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.