thinkphp路由404的根本原因是nginx未将请求转发至index.php:默认配置下nginx直接查找静态文件,失败即返回404,未进入框架路由解析;需通过try_files或rewrite规则将非静态请求重写到index.php,并确保script_filename指向正确物理路径。

ThinkPHP 路由 404 的根本原因:Nginx 没转发到 index.php
不是 ThinkPHP 配置错了,而是 Nginx 根本没把请求交给它处理。默认配置下,Nginx 会尝试直接找对应路径的静态文件(比如 /user/list),找不到就返回 404 —— 完全没机会进到 index.php 里跑路由解析。
关键在于让所有非真实静态资源的请求,都重写到 index.php 入口。这和 Laravel、CodeIgniter 等框架的 Nginx 规则逻辑一致,但 ThinkPHP(尤其是 6.x)对 PATH_INFO 或 QUERY_STRING 的依赖更敏感。
- 检查你的站点是否启用了
try_files,且最后一项是index.php而不是index.php?$query_string - 确认
fastcgi_param SCRIPT_FILENAME指向的是真实物理路径(如$document_root/index.php),不是$request_filename - 如果用了子目录部署(比如
https://example.com/app/),location块必须匹配该前缀,且重写时要保留 URI 中的路径部分给 ThinkPHP 解析
ThinkPHP 6.x 推荐的 Nginx location 块写法
以下规则适配大多数标准部署场景(根目录、无多应用嵌套、PHP-FPM Unix socket):
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
注意:try_files 第三项必须带 $query_string,否则 URL 中的参数(如 ?id=123)会丢失;SCRIPT_FILENAME 必须用 $document_root$fastcgi_script_name,不能简写成 $request_filename —— 后者在重写后可能指向错误路径。
- 如果你用的是 ThinkPHP 5.1,请把
try_files改为try_files $uri $uri/ /index.php?s=$uri&$query_string(兼容 PATH_INFO 模式) - 禁用
location ~ /\.ht类规则以外的所有隐藏文件访问,避免泄露runtime/目录 - 不要加
rewrite ^(.*)$ /index.php/$1 last;这类旧式写法,TP6 默认关闭 PATH_INFO,强依赖 QUERY_STRING
常见错误现象与对应排查点
看到这些表现,基本能锁定是 Nginx 层问题:
-
GET /index.php/user/list能访问,但GET /user/list404 →try_files没生效或 location 匹配失败 - 页面打开但 CSS/JS 404 → 静态资源路径配置错(如
public/没设为 root),和路由无关,别混在一起调 - 报错
Primary script unknown→SCRIPT_FILENAME拼出来的是个不存在的路径,检查$document_root是否指向了public/目录 - 首页能打开,其他路由提示 “The requested URL was not found on this server” → Apache 风格错误文案,说明你其实还在用 Apache,不是 Nginx
子目录部署时最易忽略的 rewrite 细节
比如项目放在 /var/www/html/myapp/,域名是 https://example.com/myapp/,那么 Nginx 的 location 必须显式声明前缀,并剥离前缀后再转发:
location /myapp/ {
alias /var/www/html/myapp/public/;
try_files $uri $uri/ /myapp/index.php?$query_string;
}
location ~ ^/myapp/(.+\.php)$ {
alias /var/www/html/myapp/public/$1;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename;
include fastcgi_params;
}
这里有两个坑:alias 结尾必须带 /,且 try_files 中的 /myapp/index.php 是 URL 路径,不是文件系统路径;SCRIPT_FILENAME 在 alias 场景下用 $request_filename 更稳妥,因为 $document_root 此时已失效。
子目录部署时,APP_URL 和 URL_DOMAIN_DEPLOY 这些 PHP 配置项也要同步更新,否则生成的链接仍会漏掉 /myapp/ 前缀。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











