使用htaccess重写带可选参数的搜索URL如何避免规则冲突?
问题原因
你写的规则失效核心有两个原因:
- 同长度路径的正则完全一致,Apache的重写规则是从上到下匹配的,命中第一条带
[L]标记的规则后就会终止后续匹配,所以单段路径的第二条规则、双段路径的第二条规则永远不会被触发。 - 你当前的URL结构本身存在逻辑歧义:比如
doctor/xxx没有任何标识能区分xxx是专科还是地区,doctor/xxx/yyy也没法区分是「专科+地区」还是「地区+城市」,如果专科和地区的取值有重叠,根本没法做无错匹配。
解决方案
方案1:调整URL结构加标识(推荐,无歧义)
给不同类型的参数加路径前缀区分,比如专科前缀s、地区前缀r、城市前缀c,修改后的规则如下:
RewriteEngine On # 三段:专科+地区+城市 RewriteRule ^doctor/s/([a-zA-Z-]+)/r/([a-zA-Z-]+)/c/([a-zA-Z-]+)$ search.php?speciality=$1®ion=$2&city=$3 [L] # 双段:专科+地区 RewriteRule ^doctor/s/([a-zA-Z-]+)/r/([a-zA-Z-]+)$ search.php?speciality=$1®ion=$2 [L] # 双段:地区+城市 RewriteRule ^doctor/r/([a-zA-Z-]+)/c/([a-zA-Z-]+)$ search.php?region=$1&city=$2 [L] # 单段:专科 RewriteRule ^doctor/s/([a-zA-Z-]+)$ search.php?speciality=$1 [L] # 单段:地区 RewriteRule ^doctor/r/([a-zA-Z-]+)$ search.php?region=$1 [L]
方案2:不修改URL结构,基于专科白名单匹配
如果不能改现有URL结构,你可以把所有专科的取值整理成白名单,通过RewriteCond做前置判断,规则要按路径从长到短的顺序写:
RewriteEngine On # 三段路径固定为专科+地区+城市,无歧义 RewriteRule ^doctor/([a-zA-Z-]+)/([a-zA-Z-]+)/([a-zA-Z-]+)$ search.php?speciality=$1®ion=$2&city=$3 [L] # 双段路径:先判断第一段是不是专科,是就匹配专科+地区 RewriteCond $1 ^(cardiologist|dentist|surgeon|xxx)$ # 把所有专科的取值用|分隔补全 RewriteRule ^doctor/([a-zA-Z-]+)/([a-zA-Z-]+)$ search.php?speciality=$1®ion=$2 [L] # 不是专科的双段默认匹配地区+城市 RewriteRule ^doctor/([a-zA-Z-]+)/([a-zA-Z-]+)$ search.php?region=$1&city=$2 [L] # 单段路径:先判断是不是专科 RewriteCond $1 ^(cardiologist|dentist|surgeon|xxx)$ # 同上补全专科列表 RewriteRule ^doctor/([a-zA-Z-]+)$ search.php?speciality=$1 [L] # 不是专科的单段默认匹配地区 RewriteRule ^doctor/([a-zA-Z-]+)$ search.php?region=$1 [L]
内容的提问来源于stack exchange,提问作者narseoh
相关产品推荐
相关产品推荐

