I’m implementing an MVC pattern for my new PHP site with a URL structure like the following:
example.com/module/controller/action?params=...
Here is my .htaccess file:
Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) portal.php?mvc=$1 [QSA,L]
The rules are working mostly right, however, if I have a directory in the public space with the same name as a module, it appends ?mvc=[directory name] to the end of the URL if there is no trailing slash.
For example:
example.loc/index turns into example.loc/index/?mvc=index
but example.loc/index/ stays the same.
How can I make it so that if the user types in example.loc/index it has the same behavior as if they had included the ending slash?
This is because mod_dir’s
DirectorySlashdirective is interfering with your rewrites. Both mod_dir and mod_rewrite sit in the same URL-file mapping pipeline, and they’re both going to do their thing no matter what the other module is doing. So when mod_dir thinks a request is for a directory, and there’s a missing trailing slash, then it’s going to flag the URL to be redirected, but the URL continues down the processing pipeline where mod_rewrite does its thing to the URI. At the end of the line, both modules modified the URI and the URI was flagged to a 301 redirect, so the response to the browser is to redirect to the new URI (which has been mangled).Solution: You need to either handle the trailing slash within mod_rewrite or simply turn off
DirectorySlash(although you should note the information disclosure security warning). You can handle the trailing slash in mod_rewrite like:Make sure to add that *right under the
RewriteEngine online. You need this applied before any MVC routing happens.