thinkphp在nginx下404或需带index.php访问,根本原因是伪静态未配置或path_info未传递:必须将try_files或rewrite规则置于location ~ .php$之前,确保非静态请求兜底至index.php,并在php处理块中显式设置fastcgi_param path_info $fastcgi_path_info及fastcgi_split_path_info指令,同时php需启用cgi.fix_pathinfo=1。

ThinkPHP 在 Nginx 下跑不起来、URL 带 index.php 才能访问、或者直接 404 / “No input file specified”,基本就是伪静态没配对,或 PATH_INFO 没传进去——不是框架问题,是 Nginx 配置漏了关键环节。
ThinkPHP 的 rewrite 规则必须放在 location ~ \.php$ 之前
很多人把 if (!-e $request_filename) { rewrite ... } 写在 location ~ \.php$ 后面,结果完全不生效。因为 Nginx 匹配 location 是从上到下优先级匹配,.php 规则先命中,请求根本不会进到 location / 里去触发 rewrite。
- 必须把 rewrite 块(无论用
if还是try_files)放在location ~ \.php$之前,通常就塞在location /里 - 宝塔用户:进「网站 → 配置文件」,在
location ~ \.php$这一行上方插入规则 - 子目录部署(如
/blog/)时,正则和目标路径都要带前缀:rewrite ^/blog/(.*)$ /blog/index.php?s=$1 last; -
last不可替换成break或redirect;break会让重写后停在当前 location,无法进 PHP 处理;redirect是 302 跳转,地址栏会暴露index.php?s=xxx
PATH_INFO 支持不是开个开关就行,要三层配合
光有 rewrite 不够,ThinkPHP 路由靠 $_SERVER['PATH_INFO'] 解析路径,而 Nginx 默认不生成这个变量。它需要 PHP 解析器(PHP-FPM)、Nginx fastcgi_param、以及 PHP 自身配置三者对齐。
- PHP 配置里确保
cgi.fix_pathinfo=1(不能是 0,否则 PATH_INFO 被清空) - Nginx 的
location ~ \.php块中必须有这两行:fastcgi_param PATH_INFO $fastcgi_path_info;和fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; - 宝塔用户注意:升级 PHP 版本后,这两行常被重置为注释状态,要手动检查并取消注释
- 如果仍报
URL pathinfo not supported,临时在public/index.php开头加一行:$_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'];(仅调试,上线前删掉)
try_files 比 if 更推荐,但容易因 root 路径错配失败
try_files 是 Nginx 官方推荐的无 if 替代方案,性能更好也更安全。但它对 root 和 alias 路径极其敏感,稍有偏差就会返回 500 或 404。
- 正确写法(假设项目根目录是
/www/wwwroot/myapp,入口在public/):location / { try_files $uri $uri/ /public/index.php?$query_string; } - 关键点:
root必须指向public的父目录(即项目根),且try_files中的/public/index.php是相对于root的路径 - 如果用了
alias(比如宝塔某些模板会设alias /www/wwwroot/myapp/public/;),那try_files中的路径就不能带/public,得写成/index.php?$query_string - 一旦看到 500 错误且 error_log 提示 “Primary script unknown”,八成是
SCRIPT_FILENAME构造错了,回退用if + rewrite更稳
验证是否真正生效,别只看首页
改完配置 reload Nginx 后,别只访问 / 或 /index 就以为 OK。ThinkPHP 的路由机制只有在真实进入框架后才能体现。
- 访问一个明确不存在的路由,比如
/this-route-does-not-exist:如果返回 ThinkPHP 自带的 404 页面(含 TP logo 或 debug 信息),说明 rewrite 和 PATH_INFO 都通了;如果返回 Nginx 默认 404,说明请求根本没进 PHP - 开启 Nginx 的 rewrite 日志(
rewrite_log on;+error_log logs/rewrite.log notice;),看日志里有没有 “using configuration” 和 “rewritten to” 记录 - 在控制器里打印
dump($_SERVER['PATH_INFO']);,确认值是不是你期望的路径段(如/index/test) - TP6+ 用户特别注意:
config/app.php中的url_common_param默认是s,所以 rewrite 规则里必须用?s=$1,不是?q=$1或其他参数名
最常被忽略的其实是 PHP-FPM 层的 fastcgi_param 传递顺序和覆盖行为——哪怕 Nginx 配置全对,只要某处多写了一次 fastcgi_param SCRIPT_FILENAME 把 PATH_INFO 相关参数挤掉了,路由照样崩。调的时候建议先关掉所有自定义 fastcgi_params,只留最简必需项,再逐条加回来验证。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











