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

发布于 2024-09-17 22:53:09 字数 1165 浏览 0 评论 0原文

我有这个 .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

当我单击链接并打印 $_GET 变量时,我得到这个:

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

关于为什么它表现不佳的任何想法?


好的,我已经通过将规则重写为解决了这个问题

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

I have this .htaccess rule:

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

It should map a URL like this:

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

to this:

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

When I click on link and print $_GET variables I get this:

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

Any ideas as to why it’s behaving badly?


Ok i have fixed this by rewriting 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

衣神在巴黎 2024-09-24 22:53:09

首先:如果您可以更具体,则不应使用 .*,例如本例中的 [^/]+。因为多个 .* 会导致巨大的回溯。因此:

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

您可以使用 RegexBuddy 之类的命令来查看这些正则表达式处理方式的差异。

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

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

第一个规则将一次处理一个参数对(最后一对除外),方法是将其附加到已经存在的参数对上(请参阅QSA 标志),然后重新启动重写过程,而不增加内部递归计数器(参见 N 标志)。然后,第二条规则将重写最后一个参数对(或仅名称)并结束迭代。

但由于使用 N 标志可能很危险,因为它可能会导致无限递归,因此您也可以使用 PHP 来解析请求的路径:

$_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]

First of all: You shouldn’t use .* if you can be more specific, like in this case [^/]+. Because multiple .* can cause immense backtracking. So:

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

You can use a took like RegexBuddy to see the difference in how these regular expressions are processed.

But since mod_rewrite does only allow to reference the first nine groups (see Tim’s answer), you could use an iterative approach and process one parameter at a time:

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

The first rule will process one parameter pair at a time (except the last pair) by append it to the already existing ones (see QSA flag) and then restart the rewriting process without incrementing the internal recursion counter (see N flag). The second rule will then rewrite the last parameter pair (or just the name) and end the iteration.

But since using the N flag might be dangerous as it can cause an infinite recursion, you could also use PHP to parse the requested 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 just need this rule to pass the request through:

RewriteRule ^viewshoplatest(/|$) /viewshoplatest.php [L]
零度° 2024-09-24 22:53:09

只是为了扩展您发现的内容,您只能定义九个组用作反向引用,这就是为什么重写为无查询字符串的脚本并让脚本检查 REQUEST_URI 如果您有大量数据需要解析。

来自文档

反向引用是
形式 $N (N=0..9),这将是
替换为第N个的内容
匹配模式的组

$0 的组是整个匹配模式,为您提供剩余的九个数字可供使用。任何更高的数字都被视为后向引用,后跟一些文字数字字符。

Just to expand on what you found out, you can only define nine groups to be used as backreferences, which is why it's generally a better idea to rewrite to a script sans-query string and have the script examine REQUEST_URI in cases where you will have a lot of data to parse out.

From the documentation:

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

$0 is the entire matched pattern, giving you the remaining nine numbers to work with. Any higher number is treated as a backreference followed by some literal numeric characters.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文