1

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
MrWhite
  • 43,179
  • 8
  • 60
  • 84
armada45
  • 103
  • 9
  • 1
    Did you try https://stackoverflow.com/a/38067042/6824121 ? – Lenny4 May 03 '23 at 19:33
  • Does this answer your question? [Redirect all to index.php using htaccess](https://stackoverflow.com/questions/18406156/redirect-all-to-index-php-using-htaccess) – Lenny4 May 03 '23 at 19:53
  • I assume with #1 it should be "show public/index.php", essentially the same as #2? – MrWhite May 03 '23 at 23:12
  • 1
    @Lenny4 The linked question is actually quite a different question (which most of those answers appear to have missed). But this question has a "hidden" subdirectory, which none of the answers in the linked question address. – MrWhite May 04 '23 at 00:06

1 Answers1

1

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.

MrWhite
  • 43,179
  • 8
  • 60
  • 84