如何在.htaccess中重写含bo_table查询参数的URL?
我有以下URL:
https://example.com/bbs/board.php?bo_table=cad https://example.com/bbs/board.php?bo_table=videos https://example.com/bbs/board.php?bo_table=news
如何在.htaccess中将它们重写为如下形式?
https://example.com/cad https://example.com/videos https://example.com/news
我知道自己的重写方法在无查询字符串的URL上有效,但尝试QSA(Query String Append)标记后并未解决问题。
Options -MultiViews RewriteRule ^bbs/board.php?bo_table=cad$ /caster-cad-downloads [R=301,L,QSA] RewriteRule ^caster-cad-downloads$ bbs/board.php?bo_table=cad [END] RewriteRule ^bbs/board.php?bo_table=video$ /caster-videos [R=301,L,QSA] RewriteRule ^caster-videos$ bbs/board.php?bo_table=video [END] RewriteRule ^bbs/board.php?bo_table=news$ /news [R=301,L,QSA] RewriteRule ^news$ bbs/board.php?bo_table=news [END]
如何在仍使用%{QUERY_STRING}方法的前提下,将URL重写为不同于查询字符串的形式?比如cad对应caster-cad-downloads,videos对应caster-videos,news对应news。我尝试了下面的代码,但有问题:
RewriteCond %{QUERY_STRING} ^bo_table=(cad|videos|news)$ RewriteRule ^bbs/board\.php$ /%1 [QSD,R=301,L] # RewriteRule ^(caster-cad-downloads|caster-videos|news)$ bbs/board.php?bo_table=$1 [END] RewriteRule ^(?:caster-(cad)-downloads|caster-(videos)|(news))$ bbs/board.php?bo_table=$1 [END]
首先要明确:RewriteRule的匹配规则不包含查询字符串,所以你最初写的^bbs/board.php?bo_table=cad$这种写法无效——?在正则里是特殊字符,查询字符串必须通过RewriteCond %{QUERY_STRING}单独匹配。
下面是正确的双向重写配置(旧URL跳转新URL,新URL内部映射回旧PHP文件):
1. 旧URL永久重定向到新URL
处理用户访问旧URL的场景,跳转到简洁的新URL:
Options -MultiViews # 匹配 bo_table=cad,跳转到 /caster-cad-downloads RewriteCond %{QUERY_STRING} ^bo_table=cad$ RewriteRule ^bbs/board\.php$ /caster-cad-downloads [QSD,R=301,L] # 匹配 bo_table=videos,跳转到 /caster-videos RewriteCond %{QUERY_STRING} ^bo_table=videos$ RewriteRule ^bbs/board\.php$ /caster-videos [QSD,R=301,L] # 匹配 bo_table=news,跳转到 /news RewriteCond %{QUERY_STRING} ^bo_table=news$ RewriteRule ^bbs/board\.php$ /news [QSD,R=301,L]
QSD标记:清除原查询字符串,避免跳转后URL残留?bo_table=xxxR=301:永久重定向,对SEO友好
2. 新URL内部映射回旧PHP文件
处理用户访问新URL的场景,服务器内部调用原PHP文件,无前端跳转:
# 映射 /caster-cad-downloads 到原文件 RewriteRule ^caster-cad-downloads$ bbs/board.php?bo_table=cad [END] # 映射 /caster-videos 到原文件 RewriteRule ^caster-videos$ bbs/board.php?bo_table=videos [END] # 映射 /news 到原文件 RewriteRule ^news$ bbs/board.php?bo_table=news [END]
END标记:停止后续重写规则,避免出现循环重写
关于批量正则写法的说明
如果新URL和查询字符串值完全一致(比如cad对应/cad),可以用批量正则简化跳转规则:
RewriteCond %{QUERY_STRING} ^bo_table=(cad|videos|news)$ RewriteRule ^bbs/board\.php$ /%1 [QSD,R=301,L]
但如果新URL和查询字符串值不一致(比如cad对应caster-cad-downloads),这种批量写法就不适用,必须分开写每个规则——正则分组无法直接实现不同字符串的映射,强行合并会增加规则复杂度,反而容易出错。
你之前写的反向重写规则^(?:caster-(cad)-downloads|caster-(videos)|(news))$存在问题:第三个分组(news)对应的是$3,而非$1,导致访问/news时无法正确映射到bo_table=news。分开写规则是更清晰、更不易出错的选择。
内容的提问来源于stack exchange,提问作者user19906832

