arik
arik

Reputation: 29270

.htaccess rule precedence

I have the following rules:

RewriteRule ^app ?page=app [QSA]
RewriteRule ^app/([0-9]+) ?page=app&id=$1 [QSA]
RewriteRule ^app/([0-9]+)/edit ?page=edit&id=$1 [QSA]

My page prints the GET params. When I call /app, the following is printed:

Array ( [page] => app )

When I call /app/123 or /app/123/edit, the print remains the same. However, when I reverse the order of the commands, I get different results.

For /app/123/edit:

Array ( [page] => edit [id] => 123 )

For /app/123:

Array ( [page] => app [id] => 123 )

Why is that? Also, is there a way to change that, because it seems easier to progress through the commands in a top-to-bottom hierarchical order, rather than the reverse. Thanks in advance.

Upvotes: 1

Views: 580

Answers (2)

Erik Nedwidek
Erik Nedwidek

Reputation: 6184

Here's a really handy resource:

http://martinmelin.se/rewrite-rule-tester/

The reason the second and third do not match is that the output of your first rule wipes out the initial URI.

The actual rules you want are:

RewriteRule ^(app/?.*) $1?page=app [QSA]
RewriteRule ^(app/([0-9]+)/?.*) $1?page=app&id=$2 [QSA]
RewriteRule ^(app/([0-9]+)/edit) $1?page=edit&id=$2 [QSA]

Testing these with app/123/edit on the test page aboves shows the rules all match and apply as:

#   Match?  Rule    Resulting URL
1   yes RewriteRule ^(app/?.*) $1?page=app [QSA]    app/123/edit?page=app
2   yes RewriteRule ^(app/([0-9]+)/?.*) $1?page=app&id=$2 [QSA] app/123/edit?page=app?page=app&id=123
3   yes RewriteRule ^(app/([0-9]+)/edit) $1?page=edit&id=$2 [QSA]   app/123/edit?page=edit&id=123

I don't think the tester is handling the QSA flag correctly. I should only have to specify the new key/value pair in each rule and not have to restate the prior one(s). QSA should merge them. Your real error in your rules were to not preserve the URI.

Upvotes: 0

darma
darma

Reputation: 4747

In that case you'll have to use the "end of string" symbol $ :

RewriteRule ^app$ ?page=app [QSA]
RewriteRule ^app/([0-9]+)$ ?page=app&id=$1 [QSA]
RewriteRule ^app/([0-9]+)/edit$ ?page=edit&id=$1 [QSA]

Otherwise, since your first exp matches all of your URL forms, it is always used, and the rule checks never make it to line 2.

Upvotes: 3

Related Questions