Welcome to WebmasterWorld Guest from

Forum Moderators: Ocean10000 & incrediBILL & phranque

Message Too Old, No Replies

rewriterules for multi-level folders

4:57 am on Jun 8, 2005 (gmt 0)

10+ Year Member

I'm trying to establish different rewrite rules depending on how many folders deep in a site a user is. This is what I use for root-level files, and it works fine:
RewriteRule ^(.*) /template.php?page=$1

Navigation is dynamically generated, and if the user drops to a sub-folder below the root, I want to use a second template page, template2.php

I've tried several things, including this:
RewriteRule ^(.*)/(.*) /template2.php?page=$1
but I don't think I'm using the correct format to indicate a subfolder - ^(.*)/(.*)

How do you represent multiple levels in apache?

5:08 am on Jun 8, 2005 (gmt 0)

WebmasterWorld Senior Member jdmorgan is a WebmasterWorld Top Contributor of All Time 10+ Year Member

A) You don't. :)

B) You "match" text strings (which can, but don't necessarily describe directory structure) using regular expressions, but these text strings have no intrinsic "meaning" in mod_rewrite; They are only text strings.

The simplest way to write a "directory-level specific" pattern is to use the negative-match feature of regex, and use a pattern like ([^/]+)/, which means, "match one or more characters not equal to a slash, followed by a slash, saving the non-slash characters for later back-reference as '$1'".

So, two levels deep would look like this:
with the trailing slash optional in case it's left off in typed-in traffic.

See the references cited in our forum charter [webmasterworld.com] for more info.


1:40 am on Jun 10, 2005 (gmt 0)

10+ Year Member

I'm not having any luck on this. Can I use this in conjunction with the other rewrite rule for root level redirects?

RewriteCond %{REQUEST_URI}!^/template.php
RewriteCond %{REQUEST_URI}!^/template2.php
RewriteRule ^(.*) /template.php?page=$1
RewriteRule ^([^/]+)/([^/]+)/?$ /template2.php?page=$2

This config refuses to ever load template2.php unless I manually key it in.
I want any request in the root level to load template.php, and any request at the second level to load template2.php

What am I missing here?

2:23 am on Jun 10, 2005 (gmt 0)

WebmasterWorld Senior Member jdmorgan is a WebmasterWorld Top Contributor of All Time 10+ Year Member

A major reason your rules won't work is that your first rule will match any and all requests that the second rule could possibily match -- The pattern (.*) will accept any number of any characters, and so the first rule always overrides the rule that follows it.

Tangent: The ".*" and ".+" patterns are known as "ambiguous" or "promiscuous" and "greedy" -- they will both match as many characters as possible. This can lead to unexpected results and also to gross inefficiency in pattern-processing, because if either of those subpatterns appears early in a pattern, regex will attempt to match the entire remaining string into that subpattern. It will then have "back off" one character at a time, starting at the end of the string, trying to get a match. The number of trial matches is then proportional to the number of characters in the string. If multiple ambiguous subpatterns are used, the problem is geometrically compounded. So, avoid this situation whenever possible, and avoid ".*" and ".+" whenever you can use a more-specific pattern.

I really can't make a better recommendation to you that to study the regular-expressions tutorial cited in our charter. It will really save you a lot of time, and may even be revelatory.

With some tweaking, we get:

# Match second-level "directory" request
RewriteCond %{REQUEST_URI} !^/template2\.php
RewriteRule ^([^/]+)/([^/]+)/?$ /template2.php?page=$2 [L]
# Match first-level "directory" requests
RewriteCond %{REQUEST_URI} !^/template\.php
RewriteRule ^([^/]+/?$ /template.php?page=$1 [L]
# Match any other requests (optional and probably needs tweaking to suit you)
RewriteCond %{REQUEST_URI} !^/template\.php
RewriteRule ^(.*)/?$ /template.php?page=$1 [L]

Also note in the regex tutorial that the special characters used as operators in regular expressions must be escaped if you wish to match them as literal characters. Therefore, the "." in the RewriteCond URL-path must be preceded with a "\".

You may also need to add exclusions for images and other files that you don't want/need to handle with php scripts.