
Apache 的 .htaccess 重写规则默认不改变原始请求参数的可见性与可访问性:浏览器地址栏显示重写后的路径,但 $_GET 仍能正常读取原始 URL 中的查询参数;若需保留或注入参数,须显式使用 [QSA] 标志或在重写目标中构造。
apache 的 `.htaccess` 重写规则默认不改变原始请求参数的可见性与可访问性:浏览器地址栏显示重写后的路径,但 `$_get` 仍能正常读取原始 url 中的查询参数;若需保留或注入参数,须显式使用 `[qsa]` 标志或在重写目标中构造。
在 Web 开发中,尤其是使用 Apache + PHP 构建动态站点时,常通过 .htaccess 的 RewriteRule 实现“美观 URL”(Pretty URLs),例如将 mySite.php?q=bar&g=foo 映射为 /mySite/bookingConfirmed。但开发者常误以为重写会“覆盖”或“屏蔽”原始 GET 参数——实际上,URL 重写本质上是服务器端的内部路由映射,而非客户端跳转。理解其行为对正确获取请求数据至关重要。
✅ 正确理解 RewriteRule 的执行逻辑
RewriteRule 默认以 内部重写(internal rewrite) 模式工作:当用户访问 /mySite/bookingConfirmed 时,Apache 在不通知浏览器的情况下,将该请求“悄悄”转发给 mySite.php,并按规则设定的参数(如 q=$1&g=$2)构造新的查询字符串。此时:
- 浏览器地址栏仍显示 /mySite/bookingConfirmed(未发生跳转);
- PHP 接收到的 $_SERVER['REQUEST_URI'] 是 /mySite/bookingConfirmed;
- 但 $_GET 数组的内容完全由重写目标中的查询字符串决定(即 q=$1&g=$2),而非原始请求中的 ?q=bar&g=foo。
⚠️ 注意:你提供的示例规则存在严重语法错误:
RewriteRule ^mySite/bookingConfirmed$ mySite.php?q=$1&g=$2
此处 $1 和 $2 表示正则捕获组,但你的模式 ^mySite/bookingConfirmed$ 并未定义任何捕获括号 (),因此 $1、$2 均为空值。正确写法应为:
# 若需从路径提取参数,例如 /mySite/bookingConfirmed/bar/foo RewriteRule ^mySite/bookingConfirmed/([^/]+)/([^/]+)$ mySite.php?q=$1&g=$2 [L] # 或更安全地:匹配固定路径,硬编码参数(适用于无动态值场景) RewriteRule ^mySite/bookingConfirmed$ mySite.php?q=bar&g=foo [L]
✅ GET 参数的来源:原始请求 vs. 重写目标
✅ 因此,回答原问题:
- 第一问:点击 href="mySite?q=bar&g=foo" 时,若无匹配规则,地址栏保持原样;若有规则但未匹配,亦不变;仅当访问 /mySite/bookingConfirmed 这类被重写的路径时,地址栏才显示美化后的 URL。
- 第二问:$q = $_GET['q']; 能否读取,取决于重写规则是否在目标 URL 中显式设置了 q= 参数。若规则未提供(如遗漏 q=$1),则 $_GET['q'] 为 null。
✅ 关键技巧:保留原始查询参数([QSA] 标志)
若需在重写后同时保留原始 URL 中的 ?q=bar&g=foo,必须添加 [QSA](Query String Append)标志:
# 示例:将 /mySite/bookingConfirmed 映射到 mySite.php,并追加原始 ?q=...&g=... RewriteRule ^mySite/bookingConfirmed$ mySite.php [QSA,L]
此时访问 http://localhost/mySite/bookingConfirmed?q=bar&g=foo,PHP 中 $_GET 将包含 ['q'=>'bar','g'=>'foo']。
? 验证方法:在 mySite.php 中加入调试代码:
<?php echo "<pre class="brush:php;toolbar:false;">"; print_r($_GET); echo "REQUEST_URI: " . $_SERVER['REQUEST_URI']; echo ""; ?>
⚠️ 注意事项与最佳实践
- 避免混淆重写与重定向:添加 [R] 标志(如 [R=301])会使 Apache 向浏览器返回 301 响应,强制跳转——此时地址栏会改变,且原始 GET 参数可能丢失(除非手动拼接)。仅在需要 SEO 友好跳转时使用。
- 始终启用 [L] 标志:防止后续规则干扰,提升可维护性。
- 路径匹配要精确:使用 ^ 和 $ 锚点避免意外匹配(如 ^mySite/bookingConfirmed$ 不会匹配 mySite/bookingConfirmed-extra)。
- 调试建议:启用 Apache 的 RewriteLog(旧版)或 LogLevel alert rewrite:trace3(Apache 2.4+),结合浏览器开发者工具的 Network 面板观察实际请求路径与响应头。
掌握重写规则中参数传递的本质,能让你精准控制数据流——无论是从第三方系统接收预订数据(如 day=2024-05-20&name=John),还是构建 RESTful 风格接口,都离不开对 $_GET 与重写逻辑的清晰认知。










