
本文详解如何在 Apache 的 .htaccess 文件中正确重写形如 /code1/code2/get?a=8&q=7 的 URL,将其映射为 get.php?c1=code1&c2=code2&a=8&q=7,并完整保留原始 GET 参数,避免参数丢失或解析失败。
本文详解如何在 apache 的 .htaccess 文件中正确重写形如 `/code1/code2/get?a=8&q=7` 的 url,将其映射为 `get.php?c1=code1&c2=code2&a=8&q=7`,并完整保留原始 get 参数,避免参数丢失或解析失败。
在 Apache 的 URL 重写中,直接在 RewriteRule 中拼接 $3(即匹配到的查询字符串)并不能自动继承原始请求中的 QUERY_STRING,因为默认情况下 RewriteRule 的模式(pattern)只匹配路径部分(path),不包含问号(?)及之后的内容。因此,原规则 ^([^/]+)\/([^/]+)\/get?(.*)$ 中的 (.*) 实际无法捕获 ?a=8&q=7 —— 因为 ? 是 URL 的分隔符,不属于路径,不会被正则匹配到。
✅ 正确做法是:仅匹配路径结构,再通过 [QSA](Query String Append)标志自动追加原始查询参数。
✅ 推荐方案:使用 [QSA] 标志(简洁、标准、可靠)
在 .htaccess 中配置如下:
对设计或页面进行 WCAG 2.1 AA 无障碍审计。触发关键词:“audit accessibility”、 “check a11y”、 “is this accessible?” 或在审查设计时使用。
RewriteEngine On # 跳过对 get.php 自身的重写,避免循环 RewriteRule ^get\.php$ - [L] # 匹配 /code1/code2/get 形式,提取 code1 和 code2,并透传所有原始 GET 参数 RewriteRule ^([^/]+)/([^/]+)/get$ /get.php?c1=$1&c2=$2 [L,QSA]
? 关键说明:
^([^/]+)/([^/]+)/get$精确匹配路径,不包含?及后续参数;[QSA]会自动将原始请求中的?a=8&q=7追加到重写后的 URL 后,最终等效于:GET /get.php?c1=code1&c2=code2&a=8&q=7;- 不需要手动解析
$_SERVER['REQUEST_URI'],更安全、可维护性高。
✅ 对应 get.php 的推荐写法(无需复杂解析)
<?php // 直接获取重写后合并的全部参数(由 QSA 自动注入) echo htmlspecialchars($_GET['c1']) . "<br>"; echo htmlspecialchars($_GET['c2']) . "<br>"; echo htmlspecialchars($_GET['a'] ?? 'N/A') . "<br>"; echo htmlspecialchars($_GET['q'] ?? 'N/A') . "<br>"; ?>
✅ 输出结果:
code1 code2 8 7
⚠️ 注意事项与常见误区
- ❌ 不要尝试在 RewriteRule 模式中匹配
?:.htaccess的RewriteRule默认不处理查询字符串,?不是路径的一部分,正则无法捕获; - ❌ 避免手动解析
$_SERVER['REQUEST_URI']:该方式易受编码、特殊字符、空格、恶意输入影响,且绕过 PHP 的$_GET安全机制(如自动 URL 解码、类型过滤); - ✅ 始终启用
[L]终止后续规则,防止意外覆盖; - ✅ 若部署在子目录(如
http://example.com/sub/),建议添加RewriteBase /sub/; - ✅ 开发时开启 Apache 的
RewriteLog(旧版)或使用LogLevel alert rewrite:trace3(新版)调试重写流程。
✅ 验证建议
- 创建测试
.htaccess并确保AllowOverride All在虚拟主机配置中启用; - 访问
http://127.0.0.1/code1/code2/get?a=8&q=7; - 检查响应是否完整输出四个值,同时用浏览器开发者工具确认网络请求状态码为
200,无重定向; - 查看
error.log确认无mod_rewrite报错。
通过 [QSA] 标志,你既能保持 .htaccess 规则的简洁性,又能完全兼容标准 PHP 的 $_GET 行为——这才是生产环境应采用的最佳实践。

















