ThinkPHP 6.1 容器部署伪静态需三者严格对齐:Nginx root 必须指向 /public 目录;使用 try_files $uri $uri/ /index.php?s=$uri&$args; 替代 if 判断;显式传递 PATH_INFO 和 SCRIPT_FILENAME,子目录部署需精确匹配 location 前缀。

ThinkPHP 6.1 容器部署时,伪静态不是靠 .htaccess 或宝塔“一键选择”实现的,而是必须由 Nginx(或 Apache)在容器内正确转发请求到 public/index.php,并确保路由参数完整透传。核心矛盾在于:容器里没有动态面板,所有规则要写死在配置文件中;且 Web 根目录必须是 public/,否则伪静态根本无法启动。
必须把 Nginx 的 root 指向 public 目录
很多部署失败,第一关就卡在这里。
- ❌ 错误:
root /var/www/html;(指向项目根目录) - ✅ 正确:
root /var/www/html/public;(Nginx 直接从 public 下找资源)
这样/about请求才会被识别为public/about→ 不存在 → 触发重写规则,而不是去项目根下找about。
使用 try_files 替代 if 判断(推荐且安全)
Nginx 官方不建议在 location 中用 if (!-e $request_filename),容易引发重定向循环。改用语义清晰、性能更优的 try_files:
location / {
try_files $uri $uri/ /index.php?s=$uri&$args;
}-
$uri:匹配静态文件(如 CSS、JS、图片) -
$uri/:匹配目录(如/admin/) -
/index.php?s=$uri&$args:兜底交给框架,&$args不能省,否则?page=2&lang=en这类参数会丢失
注意:该规则写在
server块内,且必须配合root /path/to/public;才生效。立即学习“PHP免费学习笔记(深入)”;
容器内 PATH_INFO 要显式传递(关键细节)
ThinkPHP 6.1 默认从 $_GET['s'] 解析路由,但部分中间件(如多语言前缀 /zh/about)或兼容模式仍依赖 PATH_INFO。为防万一,建议在 fastcgi_param 中补全:
fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
尤其当你的 URL 是 /en/product/123 这类结构时,$fastcgi_path_info 能确保 /en/product/123 这段被正确提取并传入 PHP。
子目录部署需额外适配(如 /myapp/)
如果项目不是部署在域名根路径,而是二级目录(例如 https://example.com/myapp/),则:
- location 块必须精确匹配:
location /myapp/ { - rewrite 目标要带前缀:
rewrite ^/myapp/(.*)$ /myapp/index.php?s=/$1 last; - 或更稳妥地用
try_files:location /myapp/ { alias /var/www/html/public/; try_files $uri $uri/ /myapp/index.php?s=$uri&$args; }
同时确认 public/index.php 中的 define('APP_PATH', __DIR__ . '/../app/'); 等路径定义不受影响(通常默认即可)。
不复杂但容易忽略



















