nginx root未指向public目录导致页面空白、类找不到或敏感文件暴露;必须将root设为public绝对路径,配try_files和正确script_filename,子目录用alias,多版本分server块,加安全限制与调试验证。

如果您在部署 ThinkPHP 项目时发现页面空白、Class 'think\App' not found 或敏感目录(如 config/、.env)可被直接访问,则极大概率是 Nginx 的 root 指令未正确指向 public 目录。以下是确保 ThinkPHP 正常运行的多种配置方案:
一、标准单项目部署:root 指向 public 绝对路径
ThinkPHP 6+ 强制要求 Web 服务器 document_root 必须为项目内 public 子目录的绝对路径,这是由其统一入口 public/index.php 和自动加载机制决定的;若指向项目根目录,vendor/autoload.php 将无法加载,且 config/、app/ 等目录会暴露在 HTTP 可访问范围内,构成严重安全风险。
1、确认项目完整路径,例如:/var/www/myapp,其中 public 目录位于 /var/www/myapp/public。
2、编辑 Nginx 站点配置文件(如 /etc/nginx/sites-available/myapp),在 server 块中设置:root /var/www/myapp/public;(注意:末尾不可加斜杠)。
3、添加必需的 try_files 指令:try_files $uri $uri/ /index.php?$query_string;
4、在 location ~ \.php$ 块中,确保 fastcgi_param SCRIPT_FILENAME 为:fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
二、子目录部署:使用 alias 替代 root
当需将 ThinkPHP 项目部署在域名子路径下(如 https://example.com/tp6/),不能使用 root 指令,否则会导致路径拼接错误;必须改用 alias,并精确匹配 location 前缀与 public 目录物理路径,避免 /tp6/tp6/index.php 类型的解析失败。
1、在 server 块内定义 location 前缀:location /tp6/ {
2、设置 alias 为 public 目录的绝对路径,结尾必须带斜杠:alias /var/www/myapp/public/;
3、配置 try_files 使用相对于 alias 的路径:try_files $uri $uri/ /tp6/index.php?$query_string;
4、在嵌套的 location ~ \.php$ 中,使用 $request_filename 替代 $document_root:fastcgi_param SCRIPT_FILENAME $request_filename;
三、多版本共存:独立 server 块 + 分离 root
在同一台服务器上同时运行 ThinkPHP 5.1、6.x 和 8.x 时,各版本虽入口结构相似,但 runtime 缓存、配置加载路径及 PATH_INFO 解析行为存在差异;若共用同一 root 或混用 location,极易引发脚本解析错位或 open_basedir 权限拒绝。必须为每个版本分配独立 server 块,且 root 明确隔离。
1、为 v5.1 项目新建 server 块,设置:server_name tp5.example.com; root /var/www/thinkphp5/public;
2、为 v6.0 项目新建 server 块,设置:server_name tp6.example.com; root /var/www/thinkphp6/public;
3、每个 server 块内均启用 PATH_INFO 支持:fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info;
4、每个 PHP 处理块中强制使用 realpath:fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
四、安全加固:防止 public 外目录越权访问
即使 root 已指向 public,若项目根目录权限宽松或父级目录可被 Nginx 进程 traverse,仍可能通过构造路径(如 /../config/database.php)间接读取敏感文件;需从文件系统层阻断遍历可能,而非仅依赖 Nginx 配置。
1、检查项目根目录权限:ls -ld /var/www/myapp,确保组和其他用户无执行(x)权限。
2、确认 runtime 目录位于项目根目录下(即 /var/www/myapp/runtime),并赋予 web 用户读写权限:chown -R www-data:www-data /var/www/myapp/runtime
3、在 Nginx 配置中显式禁止访问敏感路径:location ~ ^/(application|config|route|common|\.env|\.git|\.svn) { deny all; }
4、验证 open_basedir 是否限制在项目根目录:php_admin_value open_basedir "/var/www/myapp:/tmp"(该指令需置于 fastcgi_params 或 php-fpm pool 配置中)。
五、调试验证:确认 root 生效且路径解析正确
Nginx 配置修改后不重载或未验证 SCRIPT_FILENAME 实际值,可能导致看似生效实则路由 404;必须通过日志与 PHP 脚本双重确认 Nginx 是否真正将请求交由 public/index.php 处理,并正确注入 PATH_INFO。
1、临时在 public/index.php 开头插入调试代码:file_put_contents('/tmp/nginx_path.log', print_r($_SERVER, true), FILE_APPEND);
2、访问任意路由(如 /index/test),查看 /tmp/nginx_path.log 中的 SCRIPT_FILENAME 值是否为:/var/www/myapp/public/index.php
3、检查 PATH_INFO 是否非空:$_SERVER['PATH_INFO'] 应等于 '/index/test'
4、执行 nginx -t 验证语法,再运行 systemctl reload nginx 生效配置。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











