重写任意数量的path段来查询参数

我有这个.htaccess规则:

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

它应该像这样映射一个URL:

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

对此:

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

当我点击链接并打印$_GETvariables时,我得到这个:

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

任何想法,为什么它performance不好?


好的,我通过重写规则来解决这个问题

 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 

首先:你不应该使用.*如果你可以更具体的,就像这种情况下[^/]+ 。 因为多个.*会导致巨大的回溯。 所以:

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

您可以使用像RegexBuddy一样的方式来查看这些正则expression式的处理方式。

但是由于mod_rewrite只允许引用前九个组(请参阅Tim的答案 ),您可以使用迭代方法并一次处理一个参数:

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

第一条规则将通过将其追加到已经存在的参数对(参见QSA标志)来一次处理一个参数对(除最后一对之外),然后在不递增内部recursion计数器(参见N标志)的情况下重新启动重写过程。 第二条规则将重写最后一个参数对(或名称)并结束迭代。

但是由于使用N标志可能是危险的,因为它可以导致无限的recursion,所以你也可以使用PHP来parsing请求的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; } 

现在您只需要通过以下规则来传递请求:

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

为了扩展你发现的内容,你只能定义9个组作为反向引用,这就是为什么重写脚本sans-querystring通常是一个好主意,并且在你将要使用的脚本中检查REQUEST_URI很多数据parsing出来。

从文档 :

反向引用是$ N(N = 0..9)forms的标识符,它将被匹配模式的第N个组的内容replace

$0是整个匹配模式,给你剩下的九个数字来处理。 任何更高的数字被视为反向引用,后跟一些文字数字字符。