Apache的.htaccess规则不能原样搬到Nginx,必须重写为Nginx原生语法,否则404或500是大概率结果;因Nginx不解析.htaccess、不支持mod_rewrite标志,且默认不传递PATH_INFO,需改用try_files或正确rewrite至/index.php?s=$1并保留$arg。

直接说结论:Apache的.htaccess规则不能原样搬到Nginx,必须重写为Nginx原生语法,否则404或500是大概率结果。
为什么RewriteRule ^(.*)$ index.php/$1在Nginx里不生效
Nginx不解析.htaccess,也不支持mod_rewrite的[QSA,PT,L]标志。Apache那条规则依赖PATHINFO模式(即index.php/xxx),而Nginx默认不传递PATHINFO,必须显式拼接s=参数。
-
index.php/$1→ Nginx会尝试访问真实路径/index.php/xxx,但该路径不存在,直接报404 - 正确做法是把请求重写成
/index.php?s=$1,让ThinkPHP从$_GET['s']中解析路由 - 如果项目用了子目录(如
/admin/),$1需手动截断或用rewrite加前缀处理
if (!-e $request_filename) 是常见但危险的写法
很多文档抄来抄去用if判断文件是否存在,但Nginx官方明确不推荐在location块中使用if,尤其搭配rewrite时易引发循环重定向或逻辑错乱。
- 优先用
try_files替代:try_files $uri $uri/ /index.php?s=$uri&$args; -
try_files性能更好,语义更清晰:先查静态资源,查不到就交给index.php - 注意
&$args不能漏,否则URL中的查询参数(如?page=2)会丢失 - 若用
if写法,last和break不能混用;last会重新匹配location,break则终止重写 —— 多数场景应选last
ThinkPHP版本影响s=参数的实际接收方式
TP5/6默认走$_GET['s'],但部分定制版或启用了url_html_suffix等配置时,入口行为可能变化。
立即学习“PHP免费学习笔记(深入)”;
- 确认框架是否开启路由:
'url_route_on' => true(TP5)或'route_enable' => true(TP6) - 检查
config/app.php中url_pathinfo_fetch值,若为['PATH_INFO', 'REQUEST_URI'],说明仍兼容PATHINFO,但Nginx不传PATHINFO,所以必须靠s= - TP6.1+若启用
fastcgi_finish_request或Swoole,伪静态规则仅作用于HTTP层,不影响常驻进程 —— 此时规则只决定初始请求怎么进入口,后续路由由框架接管
最易被忽略的是try_files末尾的&$args,少写这个,所有带?的请求都会丢参;另外,Nginx配置改完必须nginx -t && nginx -s reload,光改文件不重载等于没改。



















