如何在.htaccess中按尾随斜杠数量配置RewriteRule避免规则覆盖
解决RewriteRule规则覆盖问题的两种方案
你的问题根源在于原规则中使用了.*?这种非贪婪通配符,它允许捕获组包含斜杠,导致短规则(第一条)会意外匹配更长的URL。比如访问/page/news/national/2/1时,第一条规则的(.*?)会分别捕获news和national/2/1,直接触发重写并终止后续规则执行。
下面提供两种可靠的解决方法,优先推荐第一种,因为它更直观且性能更好:
方案一:精确匹配路径段(推荐)
修改正则表达式,用[^/]+代替.*?——[^/]+会匹配不包含斜杠的单个路径段,确保每个捕获组只对应一个URL分段,从根本上避免规则跨段匹配。
同时,为了兼容URL结尾带/或不带/的情况,在每个规则末尾添加/?(表示可选的结尾斜杠)。
完整配置如下:
# 匹配 /page/mnu/id/ 或 /page/mnu/id RewriteRule ^page/([^/]+)/([^/]+)/?$ page.php?mnu=$1&id=$2 [L] # 匹配 /page/mnu/submnu/id/subid/ 或 /page/mnu/submnu/id/subid RewriteRule ^page/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ page.php?mnu=$1&submnu=$2&id=$3&subid=$4 [L] # 匹配 /page/mnu/submnu/submnusub/id/subid/subidsub/ 或不带结尾斜杠的版本 RewriteRule ^page/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ page.php?mnu=$1&submnu=$2&submnusub=$3&id=$4&subid=$5&subidsub=$6 [L]
为什么这个方案有效?
[^/]+严格限制每个捕获组只能是单个路径段(比如news、national),不会包含斜杠,因此第一条规则只能匹配page后跟着2个路径段的URL,不会误匹配更长的URL。/?兼容了带/和不带/的URL格式,提升了灵活性。- 规则顺序依然可以保持现有顺序,因为短规则不会再匹配长URL,后续规则能正常触发。
方案二:用RewriteCond检查斜杠数量
如果你更倾向于通过斜杠数量来区分规则,可以添加RewriteCond来统计请求URI中的路径段数量,确保每个规则只处理对应长度的URL:
# 仅匹配page后带2个路径段的URL RewriteCond %{REQUEST_URI} ^/page/[^/]+/[^/]+/?$ RewriteRule ^page/(.*?)/(.*?)/?$ page.php?mnu=$1&id=$2 [L] # 仅匹配page后带4个路径段的URL RewriteCond %{REQUEST_URI} ^/page/[^/]+/[^/]+/[^/]+/[^/]+/?$ RewriteRule ^page/(.*?)/(.*?)/(.*?)/(.*?)/?$ page.php?mnu=$1&submnu=$2&id=$3&subid=$4 [L] # 仅匹配page后带6个路径段的URL RewriteCond %{REQUEST_URI} ^/page/[^/]+/[^/]+/[^/]+/[^/]+/[^/]+/[^/]+/?$ RewriteRule ^page/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)/?$ page.php?mnu=$1&submnu=$2&submnusub=$3&id=$4&subid=$5&subidsub=$6 [L]
注意事项
这种方案本质上和方案一的逻辑类似,都是通过限制路径段数量来避免覆盖,但正则的可读性稍差,不如方案一直接。测试时,访问/page/news/national/2/1会被第二条规则的条件匹配,跳过第一条规则,最终得到正确的$_GET参数。
内容的提问来源于stack exchange,提问作者Dipak
相关产品推荐
相关产品推荐

