【发布时间】:2011-10-09 12:38:18
【问题描述】:
我正在尝试将 1 个动态 URL 重写为另一个动态 URL,如下所示;
/category?category=News to
/categorysearch/result/?q=news
我想知道是否有人知道如何在 htaccess 中完成此操作?
谢谢。
【问题讨论】:
标签: apache .htaccess mod-rewrite
我正在尝试将 1 个动态 URL 重写为另一个动态 URL,如下所示;
/category?category=News to
/categorysearch/result/?q=news
我想知道是否有人知道如何在 htaccess 中完成此操作?
谢谢。
【问题讨论】:
标签: apache .htaccess mod-rewrite
所以最终的 EDITED 解决方案是(对于您链接的 .htaccess):
RewriteCond %{REQUEST_FILENAME} ethical [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)ethical(=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=%3 [L,R]
如果我使用当前问题中的“类别”术语:
RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)category(=|%3D)([^&]+) [NC]
RewriteRule .* /categorysearch/result/?q=%3 [L,R]
但是第一个比较清楚,类别这个词不是到处都用的。如果您想添加小写转换,我们甚至会这样做:
# outside of a Directory section
RewriteMap lowercase int:tolower
# in a Directory section (not a .htaccess)
RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)category(=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%3} [L,R]
但正如评论 最后一个 tolower 不能在 .htaccess 中工作 - 无论如何 .htaccess 很糟糕,真的,对于表演,你真的应该考虑设置 AllowOverride None 并移动所有这些虚拟主机中的东西。诸如 rewriteMaps 之类的好东西不能用于 .htaccess 文件。
所以现在我将解释规则。首先,您遇到的主要问题是 "?" 之后的所有内容都是 query_string,而不是 请求的文件名。大多数 rewriteRules 尝试处理请求的文件名。所以我首先检查我们是否在目标请求的文件名上:
RewriteCond %{REQUEST_FILENAME} category [NC]
然后我们将处理查询字符串(问号之后的所有内容)。我们可以写一些更简单的东西:
RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} ^category=(.+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%1} [L,R]
在可用于 RewriteRule 的变量 %1 中捕获 ?category= 之后的所有内容。但是 QUERY_STRING 参数有几个问题,让我们尝试一下:
已编辑:
我的第一个答案是:
RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} [^|&|%26|%20][category](=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%2} [L,R]
[^|&|%26|%20] 发现它可能是起始参数或 & 或空格之后的参数,%26 是 & urlencoded。
但这是错误,感谢@mootinator 评论,我已经检查了更多,[category] 匹配 'category' 但也匹配 'atcatcategory' 和这些字母的任何组合。
RewriteCond %{QUERY_STRING} category(=|%3D)([^&]+) [NC]
匹配 'category' 参数,删除 ^ 允许将此参数放置在任何位置。但这也将匹配名为subcategory 的参数。所以第一个字母必须是空格或&(或查询字符串的开头)。
这就是 [^|&|%26|%20] 的原因,对我来说,这意味着链 OR & 或空格或 & 以 urlencoded 开头。但这也是错误,^ 里面的[] 表示否定。所以我们也需要在这里使用匹配括号:(^|&|%26|%20),现在它可以工作了,唯一的问题是参数的值现在是 %3 而不是 %2
然后我们捕获(类别)单词,实际上我们应该逐个字母地捕获它,大写、小写和大小写字母的 urlencoded 版本,就像一个糟糕的[c|C|%43|%63][a|A|%61|%41][t|T|%74|...]to be continued --我也许应该使用括号而不是括号,见鬼,检查urlencoded characters list here。
(=|%3D) 是否是 '=' 字符 urlencoded。 我本可以使用。由于使用了第一个匹配括号,我们将不得不使用 %2 变量而不是 %1。[=|%3D],但在这种情况下%3D 匹配得不是很好,我不明白为什么(mod_rewrite 是一片奇怪的地方)
然后我们有很好的([^&]+),它表示任何东西,但不是“&”。
在这些条件之后,我们应用 RewriteRule。我们把所有东西(这是.*)重定向到/catalogsearch/result/?q=%2,我们使用%3而不是$1或$3,因为我们没有在rewriteRule上捕获任何东西,而是在之前的条件下(%3是在最后一个条件下捕获的第三个数据,所以它是([^&]+))。
如果您在 rewriteRule 中添加 QSA 标志 ([L,R,QSA]),您甚至可以在最终查询字符串中取回其他参数,以便:
ethical?bar=toto& ethical=Foo&zorglub=titi
=> is redirected to
catalogsearch/result/?q=foo&bar=toto&%2520ethical=Foo&zorglub=titi
如果我玩一点 url 编码:
ethical?bar=toto%26 ethical%3DFoo&zorglub=titi
=> is redirected to
catalogsearch/result/?q=foo&bar=toto%2526%2520ethical%253DFoo&zorglub=titi
但这还没有结束,我会让你处理所有你可能遇到的 urlencoding 问题,你想检测 Foo 值的所有变化并将它们与 tolower 混合(这里它被破坏了)。您甚至可能不会在参数或额外属性中遇到编码 url 的这些问题,但这很有趣 :-)
【讨论】:
(=|%3D) 表示= 或%3D 和[=|%3D] 表示% 或| 或3 或D,所以不,你不能使用@987654 @ 因为它根本不匹配 %3D。 ([category] 显然不是你想的那样)
根据您要做什么以及需要做的具体事情,有两种选择。
第一个是 Rob W 的解决方案,应该将用户从 /category?category=News 重定向到 /categorysearch/result/?q=News
如果您的 URL 看起来是区分大小写的,您可能需要查看如下 PHP 脚本:
$matches = array();
if( preg_match( "/^/category\?category=(.+)/", $_SERVER['REQUEST_URI'], $matches ) ) {
header( 'Location: http://' . $_SERVER['HTTP_HOST'] . '/categorysearch/result/?q= . strtolower($matches[1]) );
}
else {
//ERROR HANDLING
}
一旦确定,您可以使用如下规则使用完全小写的参数进行重定向。
RewriteRule ^category\?category=(.+)$ redirect.php [L]
总之,这个解决方案会将/category?category=News重定向到/categorysearch/result/?q=news
【讨论】:
我认为
RewriteRule ^/category?category=(.*) /categorysearch/result/?q=news
会做的。
【讨论】: