Mod_Rewrite, PHP and the .Htaccess File

mod_rewrite, php and the .htaccess file

One approach is to rewrite everything to a handling script

RewriteEngine on
RewriteBase /

# only rewrite if the requested file doesn't exist
RewriteCond %{REQUEST_FILENAME} !-s

# pass the rest of the request into index.php to handle
RewriteRule ^(.*)$ /index.php/$1 [L]

so if you have a request to http://yourserver/foo/bar/

what you actually get is a request to http://yourserver/index.php/foo/bar - and you can leave index.php to decide what to do with /foo/bar (using $_SERVER['PATH_INFO'] -tom)

You only need to modify .htaccess the first time. All future requests for inexistent files can then be handled in PHP.

You might also find the docs for mod_rewrite useful - but keep it simple or prepare to lose a lot of sleep and hair tracking down obscure errors.

mod_rewrite interaction between two .htaccess files

As already been mentioned in comments/answer that Apache .htaccess is per-directory directive. Apache only uses closest/nearest .htaccess so in your case it is only using /product/blog/.htaccess and ignoring /.htaccess:

You can use this directive at top of your /product/blog/.htaccess:

RewriteOptions InheritBefore

This will make rules from the parent scope are applied before rules specified in the child scope.

Here is Apache documentation

.htaccess, use mod_rewrite to rewrite to a file OUTSIDE the web root

Short answer: no. The webserver can't directly access files outside of the document root. If you think about it, there would be quite a security problem if it could. What you can do is rewrite to a file within the document root that includes or reads from the file that is located outside of the root. (Moved from comments...)

how to write mod_rewrite rule in .htaccess

If I understand what you need, this will do it:

RewriteEngine On
RewriteRule ^(.*)project/(.*)/(.*).php$ /$2/$3.php [L,R=301]
RewriteRule ^(.*)project/(.*).php$ /$2.php [L,R=301]
RewriteRule ^(.*)project/(.*)test$ /new_test.php [L,R=301]
RewriteRule ^(.*)project/(.*)$ /test.php [L,R=301]

By the way, the order of the rules here is very important, so you have to keep it exactly the same.

mod_rewrite is enabled, .htaccess file is ok, but requests are not going through index.php

You should check if for that specific directory (root folder of your project), apache is configured to allow overriding through .htaccess.

If you want to allow such override, the directives found in apache.conf or the specific settings for your virtual host should look like this:

<Directory /var/www/>
AllowOverride All
Require all granted
</Directory>

How can I use the .htaccess file to rewrite URL's for a subdirectory?

Just to be sure, I should be able to put another .htaccess in a subdirectory and expect it to rewrite the urls for example.com/sub, right?

Yes. The mod_rewrite directives in the /subdir/.htaccess file will, by default, completely override the mod_rewrite directives in the parent/root .htaccess file. However, you will need to redefine the ErrorDocument directives in order to override the root.

RewriteCond %{REQUEST_FILENAME}/index.html !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f

To clarify, with these two conditions are you wanting to occasionally serve the index.html or index.php (DirectoryIndex) document from a requested subdirectory, instead of routing the request to /index.php in the document root? In this case it would be more common (and marginally more optimal) to simply check that the request does not map to a directory instead (ie. RewriteCond %{REQUEST_FILENAME} !-d). Unless there are some physical subdirectories that you want to route to /index.php in the document root?

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}/index.html !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule . index.php [L]
</IfModule>

These directives could be simplified slightly - and this will help you if you want to apply the same directives to the subsite in /subdir (and serve /subdir/index.php instead).

Remove the RewriteBase directive entirely. The relative susbtitution string, ie. index.php, will then be relative to the directory where the .htaccess file is located (or inherited).

You also don't need the <IfModule mod_rewrite.c> wrapper. See my answer to the following question on the Webmasters Stack for more information on this: https://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary

So, the above can be written:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}/index.html !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule . index.php [L]

(And note my comment above about replacing the two conditions with a directory check instead.)

Now, you could simply copy the exact same directives into the /subdir/.htaccess file and these will now route requests to /subdir/index.php instead, overriding the mod_rewrite directives in the parent.

No need to copy Options -Indexes, unless you want to change this option.

OR, if you want to apply the exact same directives (but in relation to the /subdir) you could simply enable mod_rewrite inheritance in the /subdir/.htaccess file. For example:

# /subdir/.htaccess

ErrorDocument 403 /subdir/404.php
ErrorDocument 404 /subdir/404.php

RewriteEngine On
RewriteOptions Inherit

The effect of RewriteOptions Inherit is to essentially "copy" the mod_rewrite directives from the parent config, ie. /.htaccess in the root, behind the directives in the current /subdir/.htaccess file. It is important to clarify that the directives are "copied", they are not run in-place as if in the root /.htaccess file.



Related Topics



Leave a reply



Submit