Why does this .htaccess
work when accessing example.com/mywebsite/
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php
whereas this fails (404):
RewriteEngine On
RewriteRule ^(.*)$ index.php
I thought the second solution should work as well.
RewriteCond means a condition must be true in order for the next RewriteRule to be processed. %{REQUEST_FILENAME} is a variable set by the server to contain the request URL, not just a filename as it may appear. The -f flag without the ! means the condition is true if the first argument resolves to a valid file.
RewriteCond %{REQUEST_FILENAME} !-d. … means that if the file with the specified name in the browser doesn't exist, or the directory in the browser doesn't exist then procede to the rewrite rule below. QReyes May 4, 2005, 2:07am #4.
htaccess rewrite rules can be used to direct requests for one subdirectory to a different location, such as an alternative subdirectory or even the domain root. In this example, requests to http://mydomain.com/folder1/ will be automatically redirected to http://mydomain.com/folder2/.
The <IfModule mod_rewrite. c>... </IfModule> block ensures that everything contained within that block is taken only into account if the mod_rewrite module is loaded. Otherwise you will either face a server error or all requests for URL rewriting will be ignored.
In order to explain this behaviour, we need to make some assumptions about your file system, and by "work" you mean that a file is served (you don't see a directory listing)...
The .htaccess
file is located in the document root and /mywebsite
is a physical directory that contains an index.php
file (or some DirectoryIndex
document). There is no index.php
file in the document root. In other words:
example.com/
.htaccess
mywebsite/
index.php
In this scenario, when you request example.com/mywebsite/
the following happens:
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php
/mywebsite/
is a physical directory, so the first condition fails and the RewriteRule
is not processed.
mod_dir then searches for a DirectoryIndex
, finds index.php
and the .htaccess
file is reprocessed. This now maps to a physical file, so the second condition fails and the RewriteRule
is not processed.
The net result is that example.com/mywebsite/index.php
gets requested. The same as if there was no .htaccess
file at all.
RewriteRule ^(.*)$ index.php
However, in this scenario, there are no conditions. The RewriteRule
gets processed unconditionally and internally rewrites the request to example.com/index.php
(strictly speaking it's <filesystem-path-to-document-root>/index.php
) since that is where the .htaccess
file is located.
However, there is no index.php
file in the document root; hence the 404.
Why is
RewriteCond %{REQUEST_FILENAME} !-d
mandatory?
Whether it is mandatory or not is really dependent on your filesystem and what you are trying to do. But generally, you don't normally want physical directories to be processed by the front controller.
The !-f
condition is usually more important since you often don't want physical files to be processed by the front controller. This is required when you want to serve static resources (eg. CSS, JavaScript and images) from the same area on the filesystem. However, you might omit this directive if you wanted to control access to some physical files (perhaps a "download" section) through the front controller.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With