Rewrite rule for multiple request variables

I currently have the following rewrite rule in my .htaccess:

RewriteEngine On
Options +FollowSymlinks
RewriteRule ^/?([a-zA-Z]+)/([a-zA-Z]+) index.php?controller=$1&action=$2

This works fine, but i have the following uri’s which are not caught by the rule:

mysite.com/news
mysite.com/news/delete/34

So i can see whats happening: the rewrite rule is matching exactly 2 arguments. Can i add optional parameters to this rule? Or do i add more rules to catch the other uri structures: should i add a rewrite rule for each possible structure (eg 1 rewrite rule for 1 arg, a second rewrite rule for 2 args (as above), a third rewrite rule for 3 args etc)?

Thanks.

sm,

Hmmm, that looks familiar - except for the lack of terminating that RewriteRule statement with a Last flag! Don’t forget that as it’s more than good practice, it’ll otherwise disable nearly anything after it as it’s automatically AND’ed.

Now, you’ve hit the nail on the head: Your code deals with EXACTLY two strings within the URI. To deal with any other number, you’ll either have to write one statement for each OR combine them into a single statement. As an example (based on what appears to be an id for the last character set):

RewriteRule ^/?([a-zA-Z]+)(/([a-zA-Z]+)(/([0-9]+))?)?$ index.php?controller=$1&action=$3&id=$5 [L]

In this strange looking beast, $1 is the same first ([a-zA-Z]+) atom as before.

$2 is eveything that follows and is optional which enables the single variable URI.

Within $2 is the second ([a-zA-Z]+) atom which is $3 and everything that follows is the optional $4 so that the two variable solution is also enabled.

Within $4 is the final ([0-9]+) atom which is $5 and is the end of the three variable solution.

NOTE that this only works if the variables are ALWAYS in this order, i.e., controller will always be the first, action will always follow controller and, if id is present, it’s always last.

I’d do it this way but I know to be exceptionally careful about how the atoms are created. If you’re not used to this, creating your own three rule set may be much safer.

Regards,

DK

Thanks for your reply dklynn.

Your single-line rewrite rule works great, but for clarity i’m trying to convert it to 3 individual rewrite rules. The main reason for this is that i can’t be 100% certain that no more parameters will be added to the request, and laid out this way, i can easily see the rewrite rule for a request with 1 to N parameters, if that makes sense. Plus i think i might have a better chance of writing a successful rewrite myself instead of trying to adjust a complex one.

Anyway…

I’ve broken it down to these three rules:


RewriteEngine On
Options +FollowSymlinks
RewriteRule ^/?([a-zA-Z]+) index.php?controller=$1
RewriteRule ^/?([a-zA-Z]+)/([a-zA-Z]+) index.php?controller=$1&action=$2
RewriteRule ^/?([a-zA-Z]+)/([a-zA-Z]+)/([0-9]+) index.php?controller=$1&action=$2&id=$3 [L]

These seem to be right but are not working - do i need to put it in the reverse order ie so that 1 request parameter is at the bottom?

Another problem is that if someone types mysite.com/user/ <– the trailing slash, i get a page not found error, which i figure is the trailing slash causing the rewrite rule to be unrecognised. What i’m looking for is “ends with an optional backslash”. I’ve been tinkering with /$? at the end of the rewrite rule but that causes an internal error. :mad:

Thanks.

sm,

The first problem is that you failed to terminate the first two RewriteRule statements (DON’T forget those Last flags).

The second problem (input error) can be accommodated with an optional trailing slash - which should go BEFORE the missing end anchors. I.e.,

RewriteEngine On
RewriteRule ^/?([a-zA-Z]+)[COLOR=Red]/?$[/COLOR] index.php?controller=$1 [COLOR=Red][L][/COLOR]
RewriteRule ^/?([a-zA-Z]+)/([a-zA-Z]+)[COLOR=Red]/?$[/COLOR] index.php?controller=$1&action=$2 [COLOR=Red][L][/COLOR]
RewriteRule ^/?([a-zA-Z]+)/([a-zA-Z]+)/([0-9]+)[COLOR=Red]/?$[/COLOR] index.php?controller=$1&action=$2&id=$3 [L]

Regards,

DK

ahhh the last flag stops it looking for more matches once its found a pattern that matches… i see.

Thanks for your time & explanations. :cool:

sm,

No problem. Just remember that [L] is just like ; and/or } in PHP. Good programming technique requires that it be used (unless the omission is intentional - to allow the automatic AND to take place for the following rule). Saying that, it’s similar to my rule of thumb: NEVER use (.*) unless you mean to catch EVERYTHING!

Regards,

DK