动态参数重写是nginx伪静态核心,旨在将如/article/123.html转为/article.php?id=123并保留参数;推荐用rewrite指令配合正则捕获、try_files替代if、$query_string保留原始参数,并通过rewrite_log和curl验证。

动态参数重写是 Nginx 伪静态最常用场景,核心目标是把带 query string 的 URL(如 /article.php?id=123)转成更友好的路径形式(如 /article/123.html),同时后端仍能正确接收参数。关键不在“生成静态文件”,而在请求路由的精准转发。
基础 rewrite 规则写法
用 rewrite 指令匹配 URI 路径部分(不含域名和查询字符串),捕获数字、字母等参数,再拼成带 query 的目标地址:
-
rewrite ^/article/(\d+)\.html$ /article.php?id=$1 last;匹配/article/123.html,将123捕获为$1,重写为/article.php?id=123 -
rewrite ^/p/([a-zA-Z0-9_]+)$ /index.php?p=$1 last;支持字母、数字、下划线,适用于 slug 类型 ID - 注意:正则开头用
^、结尾用$,避免误匹配;括号必须是英文半角,且要转义特殊字符
推荐用 try_files 替代 if + rewrite
很多教程用 if (!-e $request_filename) 判断文件不存在再 fallback,但 if 在 location 中有坑,易引发重复执行或逻辑错乱。更稳妥的方式是直接用 try_files:
-
try_files $uri $uri/ /index.php?$query_string;先查真实文件或目录,不存在就交给index.php,并保留原始查询参数 - 如果想统一走路由入口(如 Laravel、ThinkPHP),这条一行就能替代几十行 if 判断
- 它不依赖正则匹配,性能更高,也避免了
if块中 rewrite 的作用域陷阱
参数保留与拼接技巧
原始 URL 可能自带参数(如 /news/123.html?from=weibo),重写时需主动带上:$query_string 变量可原样传递全部参数:
-
rewrite ^/news/(\d+)\.html$ /news.php?id=$1&$query_string last;这样?from=weibo会被自动附加到新 URL 后 - 若只想保留特定参数,可用
set提前提取,例如:set $from $arg_from;,再在 replacement 中引用$from - 避免写成
/news.php?id=$1?$query_string—— 多余的?会导致参数解析异常
调试与验证要点
配置后别急着 reload,先确认几个关键点:
- 打开
rewrite_log on;(放在 http/server/location 块内),配合error_log /path/to/error.log notice;查看重写过程 - 用
curl -I测试响应头,确认返回的是 200 还是意外的 301/302(flag 写错会跳转) - 检查 PHP 脚本是否真收到了参数:
var_dump($_GET);,确保$1成功传入而非空值 - location 块的路径匹配优先级会影响 rewrite 执行顺序,建议把具体规则放通用规则之前











