views:

21

answers:

1

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

RewriteRule ^([^/]+)/([^/]+)/(tab:([^/]+)/?)?(scope:([^/]+)/?)?(sort:([^/]+)/?)?(p:\d+)/?)?$ web/results.php?view=$1&q=$2&tab=$4&searchscope=$6&sortBy=$8&page=$10 [NC,QSA,L]

It seems to work great when testing on some of the online regex testers that I have found. However on this tester (which seems to be a better tester and represents exactly what I am seeing when I try to apply this rule I am seeing some strange things. http://civilolydnad.se/projects/rewriterule/

Lets way I apply it to this url: view1/harry+potter/tab:search/scope:blah/sort:cdate

What I get is web/results.php?view=view1&q=harry+potter&tab=tab:search/&scope=scope:blah/&sort=sort:cdate&p=0

What is strange to me is that I should be getting tab=search not tab=tab:search/. And the other parameters are similar.

The matching regex group 4 contains search, but if I don't use group 3 ($3) somewhere in the query, I don't get access to $4.

I must be doing something wrong. Any suggestions?

+1  A: 

I wasn't able to even get that tester to work (it doesn't return any results), so it's safe to assume that it's the tester that's wrong, not you. Also, your rule currently has a syntax error (unmatched closing parenthesis), so I'm going to assume that you meant this:

RewriteRule ^([^/]+)/([^/]+)/(tab:([^/]+)/?)?(scope:([^/]+)/?)?(sort:([^/]+)/?)?(p:(\d+)/?)?$ web/results.php?view=$1&q=$2&tab=$4&searchscope=$6&sortBy=$8&page=$10 [NC,QSA,L]

Running this on my test server with the example URL provided returns the results that you were actually expecting, almost. The page parameter will never get the expected value because $10 is not a valid RewriteRule backreference:

Back-references are identifiers of the form $N (N=0..9), which will be replaced by the contents of the Nth group of the matched Pattern

This leaves you with the following capture groups:

RewriteRule ^([^/]+)/([^/]+)/(tab:([^/]+)/?)?(scope:([^/]+)/?)?(sort:([^/]+)/?)?(p:(\d+)/?)?$
#           ^|     | |     | |    |     |  | |     *|     |  | |     |     |  | |         | ^
#            |     | |     | |    |     |  | |     0|     |  | |     |     |  | |         |
#            ^  *  ^ ^  *  ^ ^    | *   |  ^ ^      |*    |  ^ ^     | *   |  ^ ^    *    ^
#               1       2         | 3   |           |5    |          | 7   |         9
#                                 ^  *  ^           ^  *  ^          ^  *  ^
#                                    4                 6                8

However, since mod_rewrite allows PCRE and you don't actually need all of the information that's currently captured, you can just use non-capturing groups as in the following test pattern:

^([^/]+)/([^/]+)/(?:tab:([^/]+)/?)?(?:scope:([^/]+)/?)?(?:sort:([^/]+)/?)?(?:p:(\d+)/?)?$

Now we just have backreferences for the relevant portions of data, giving this modified RewriteRule:

RewriteRule ^([^/]+)/([^/]+)/(?:tab:([^/]+)/?)?(?:scope:([^/]+)/?)?(?:sort:([^/]+)/?)?(?:p:(\d+)/?)?$ web/results.php?view=$1&q=$2&tab=$3&searchscope=$4&sortBy=$5&page=$6 [NC,QSA,L]

With this, going to view1/harry+potter/tab:search/scope:blah/sort:cdate with a print_r($_GET) gives:

Array (
    [view] => view1
    [q] => harry potter
    [tab] => search
    [searchscope] => blah
    [sortBy] => cdate
    [p] =>
)
Tim Stone