子目录部署thinkphp时,location必须带路径前缀(如location /blog/ {),并配置try_files $uri $uri/ /blog/index.php?$query_string;,同时在php处理块中添加fastcgi_param path_info $fastcgi_path_info;和fastcgi_split_path_info ^(.+?\.php)(/.*)$;以确保路由和path_info正确解析。

子目录下 Nginx 的 location 必须带路径前缀
ThinkPHP 部署在 /blog/ 这类二级目录时,如果只写 location / { ... },Nginx 会把 /blog/user/login 当作根路径处理,重写目标变成 /index.php?s=/blog/user/login —— 而真实入口是 /blog/public/index.php,结果就是 404 或跳转到错误路径。
正确做法是显式声明子目录路径:
-
location /blog/ {—— 注意末尾斜杠,匹配所有以/blog/开头的请求 - 内部
rewrite或try_files的 fallback 目标必须含子目录前缀,如/blog/public/index.php?$query_string - 不能依赖
root指令自动拼接:若root设为/var/www/html,$document_root/blog/public/index.php才对;设错就找不到文件
PATH_INFO 传不进去会导致路由全挂
TP5/6 默认用 $_SERVER['PATH_INFO'] 解析 /user/login 这段路径。但在子目录中,Nginx 不会自动提取 /blog/ 后面的部分塞进 PATH_INFO,框架拿到空值,就当访问首页,所有路由失效。
必须在 location 块里加这一行:
-
fastcgi_param PATH_INFO $fastcgi_path_info;—— 缺了它,index.php/user/login就只是执行index.php,后面路径被丢弃 - 搭配
fastcgi_split_path_info ^(.+?\.php)(/.*)$;使用(放在location ~ \.php$块内),否则$fastcgi_path_info为空 - 别用
$1或正则硬编码:不同 Nginx 版本对rewrite中捕获组的解析不一致,$fastcgi_path_info是唯一可靠来源
public 目录位置和运行目录设置要咬死
TP6 入口强制在 public/,但宝塔或手动配置时极易搞错层级。比如项目物理结构是 /var/www/html/myapp/public/index.php,而站点 root 设成 /var/www/html/myapp,那 /index.php 就指向错地方。
两个关键点必须同步:
- 宝塔「运行目录」必须选
/public(开头带斜杠),不是public也不是留空 - Nginx 配置里的
root指令必须指向项目根目录(如/var/www/html/myapp),不是public子目录;否则$document_root/index.php会拼出不存在的路径 - 验证方式:直接访问
/public/index.php应能打开首页;访问/index.php应该 404
lang/ 目录放错位置会让多语言静默失效
子目录 + 多语言 + 伪静态三者叠加时,lang/ 放在 public/lang/ 或 /blog/lang/ URL 路径下,框架根本读不到——前者被当静态资源拦截,后者压根不在扫描路径里。
正确位置只有一个:
-
lang/必须和public/平级,即物理路径为/var/www/html/myapp/lang/ - 目录名严格小写:
zh-cn✅,ZH-CN❌,Linux 下大小写敏感,错一个字母就 fallback 到默认语言 - 每个语言文件必须
return数组,不能echo或print_r,否则加载失败且无报错
最常被忽略的是 fastcgi_param PATH_INFO 这一行,它不报错、不提示,只让路由失效,排查时容易绕远路。先确认这行存在,再调其他。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











