ThinkPHP在Win/Nginx下报404主因是Nginx未将请求转发至public/index.php:需配置try_files $uri $uri/ /index.php?$query_string,root必须指向public目录(如root C:/www/myapp/public;),且location ~ \.php$中须设置fastcgi_split_path_info与fastcgi_param PATH_INFO。

Win/Nginx 环境下 ThinkPHP 报 404,95% 是 Nginx 没把请求交给 public/index.php——不是路由写错了,也不是控制器不存在,是框架压根没启动。
为什么 /index.php/user/login 能通,但 /user/login 直接 404
Nginx 在 Windows 下默认行为和 Linux 一致:它会先查磁盘上是否存在 user/login 这个真实路径(文件或目录),找不到就返回 404,根本不会去调用 PHP。ThinkPHP 的路由解析完全没机会运行。
验证方法很简单:
- 用浏览器或
curl -I http://localhost/user/login,如果响应头里没有X-Powered-By: ThinkPHP,说明请求没进 PHP 层 - 访问
http://localhost/index.php?s=/user/login能显示页面 → 框架本身正常,只是伪静态没生效 - 检查 Nginx 错误日志:
logs/error.log,常见报错如"No input file specified"或"Primary script unknown",都指向SCRIPT_FILENAME拼错了
location / 块必须配 try_files,不能只靠 rewrite
Windows 版 Nginx 对 if 和 rewrite 的兼容性更脆弱,单独用 rewrite ^(.*)$ /index.php?s=$1 last; 容易导致静态资源(如 /static/js/app.js)也被强行转发给 PHP,引发 500 或加载失败。
立即学习“PHP免费学习笔记(深入)”;
正确做法是用 try_files 显式声明优先级:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
注意三点:
-
$uri匹配真实存在的文件(favicon.ico、robots.txt) -
$uri/匹配真实存在的目录(比如你有public/admin/) -
/index.php?$query_string是关键:保留原始查询参数,否则?id=123会丢失,$_GET为空
root 必须指向 public 目录,且不能用 alias
Windows 路径分隔符是反斜杠,但 Nginx 配置里一律用正斜杠。如果 root 写成 C:\www\myapp,Nginx 会把它当字符串拼接,$document_root/index.php 就变成 C:\www\myapp/index.php —— 而实际入口在 C:/www/myapp/public/index.php,必然报错。
正确写法(路径中全部使用正斜杠):
root C:/www/myapp/public;
务必检查:
- 该路径下确实存在
index.php文件 - 不要用
alias替代root:alias 在try_files中路径计算逻辑不同,Windows 下极易拼出错误物理路径 - 确认
root指令写在server { }块顶层,而不是嵌套在某个location里,否则$document_root可能为空
fastcgi_param PATH_INFO 必须显式设置,否则路由段全丢
ThinkPHP 6 默认用 PATH_INFO 模式解析 /user/login 这段路径。但 Nginx 不会自动拆解它,必须靠 fastcgi_split_path_info 和 fastcgi_param PATH_INFO 协同提取。
在 location ~ \.php$ 块里,这几行缺一不可:
fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
容易踩的坑:
- 漏掉
fastcgi_param PATH_INFO→$_SERVER['PATH_INFO']为空,/user/login全部被当成控制器名,路由匹配直接失效 -
fastcgi_split_path_info正则写错(比如多一个/或少一个?)→$fastcgi_path_info提取失败,结果一样是空 - 用
$request_filename替代$document_root$fastcgi_script_name→ Windows 下路径拼接更易出错,优先用后者
改完配置别忘了执行 nginx -t 测试语法,再 nginx -s reload。Windows 下有时服务管理器里的“重启”按钮不触发重载,建议直接命令行操作。最隐蔽的问题往往出在 PATH_INFO 提取失败——它不报错,只是让整个路由链静默失效。



















