I've this .htaccess rule:

RewriteRule viewshoplatest/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/$ /viewshoplatest.php?$1=$2&$3=$4&$5=$6&$7=$8&$9=$10&$11=$12&$13=$14&$15=$16

It will map a URL such as this:

http://www.veepiz.com/viewshoplatest/start/10/end/10/filter/0/ownerid/0/sortby/date/sortdir/DESC/cat/0/scat/0/

for this:

http://www.veepiz.com/viewshoplatest.php?start=0&end=10&filter=0&ownerid=0&sortby=date&sortdir=DESC&cat=0&scat=0

After I click link and print $_GET variables I recieve this:

Array ( [start] => 10 [end] => 10 [filter] => 0 [ownerid] => 0 [sortby] => start0 [start1] => start2 [start3] => start4 [start5] => start6 )

Any ideas why it’s acting badly?


Ok i've fixed this by spinning the rule to

RewriteRule viewshoplatest/start/(.*)/end/(.*)/filter/(.*)/ownerid/(.*)/sortby/(.*)/sortdir/(.*)/cat/(.*)/scat/(.*)/$ /viewshoplatest.php?start=$1&end=$2&filter=$3&ownerid=$4&sortby=$5&sortdir=$6&cat=$7&scat=$8

Simply to expand on which you discovered, you are able to only define nine groups for use as backreferences, and that's why it's generally a much better idea to rewrite to some script sans-query string and also have the script examine REQUEST_URI in instances where you'll have a large amount of data to parse out.

From the documentation:

Back-references are identifiers from the form $N (N=..9), which is changed through the items in the Nth number of the matched up Pattern

$0 may be the entire matched up pattern, providing you with the rest of the nine amounts to utilize. Any greater number is treated like a backreference then some literal number figures.

To begin with: You shouldn’t use .* if you're able to become more specific, as with this situation [^/]+. Because multiple .* may cause immense backtracking. So:

RewriteRule ^viewshoplatest/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/$ /viewshoplatest.php?$1=$2&$3=$4&$5=$6&$7=$8&$9=$10&$11=$12&$13=$14&$15=$16

Use a required like RegexBuddy to determine the main difference in how these regular expressions are processed.

Consider mod_rewrite does only let it reference the very first nine groups (see Tim’s answer), you could utilize an iterative approach and process one parameter at any given time:

RewriteRule ^viewshoplatest/([^/]+)/([^/]+)/([^/]+/[^/]+/.*)$ /viewshoplatest/$3?$1=$2 [QSA,N]
RewriteRule ^viewshoplatest/([^/]+)/([^/]+)/([^/]*)/?$ /viewshoplatest.php?$1=$2&$3 [QSA,L]

The very first rule will process one parameter pair at any given time (except the final pair) by append it towards the already established ones (see QSA flag) after which restart the spinning process without incrementing the interior recursion counter (see N flag). The 2nd rule will rewrite the final parameter pair (or simply the title) and finish the iteration.

Consider while using N flag may be harmful as it can certainly cause an infinite recursion, you might use PHP to parse the asked for path:

$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = implode('/', trim($_SERVER['REQUEST_URI_PATH'], '/'));
array_shift($segments); // remove path prefix "/viewshoplatest"
for ($i=0, $n=count($segments); $i<$n; ) {
    $_GET[rawurldecode($segments[$i++])] = ($i < $n) ? rawurldecode($segments[$i++]) : null;
}

Now you simply need this rule to pass through the request through:

RewriteRule ^viewshoplatest(/|$) /viewshoplatest.php [L]