HestiaCP默认Nginx配置不兼容ThinkPHP伪静态,因其fastcgi_param SCRIPT_FILENAME直接映射物理文件,未传递PATH_INFO;ThinkPHP(尤其5.x/6.x)依赖PATH_INFO解析路由(如/article/123),若$_SERVER['PATH_INFO']为空则路由失效,导致404、index.php暴露或路由不触发。

在 HestiaCP 中配置 ThinkPHP 伪静态,核心不是改 Nginx 配置文件本身,而是通过面板提供的「自定义重写规则」入口填入正确规则,并确保 PHP 运行模式兼容 PATH_INFO —— 否则无论怎么写规则,index.php 都无法被隐藏,路由也解析失败。
为什么 HestiaCP 的默认 Nginx 配置不兼容 ThinkPHP 伪静态
HestiaCP 默认使用 php-fpm 的 fastcgi_param SCRIPT_FILENAME 直接映射到物理文件,而 ThinkPHP(尤其 5.x/6.x)依赖 PATH_INFO 解析 URL 路径(如 /article/123 → index.php/article/123)。若未显式传递 PATH_INFO,$_SERVER['PATH_INFO'] 为空,路由匹配直接失效。
常见表现:
- 访问 /article/123 返回 404 或直接下载 index.php
- url_route_on => true 已开启,但 Route::rule('article/:id', 'index/article') 完全不触发
- 浏览器地址栏仍显示 index.php/article/123,伪静态形同虚设
关键点:
- ✅ HestiaCP 的「Web Domain」设置里必须勾选 PHP-FPM(非 Apache + mod_php)
- ✅ PHP 版本需 ≥ 7.4(ThinkPHP 6.1+ 强制要求)
- ✅ 不要手动编辑 /usr/local/hestia/data/web/xxx.conf —— 下次面板更新会覆盖
在 HestiaCP 后台填入正确的 Nginx 重写规则
登录 HestiaCP → 点击对应网站 → 「Web Domain」→ 滚动到底部「Custom Nginx Settings」→ 在「Additional nginx directives」文本框中粘贴以下内容(注意:不是 location / 块内,是独立 directive):
RewriteEngine on
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
}这个规则等效于官方推荐的 Nginx 伪静态,但适配 HestiaCP 的注入机制:
- rewrite ^(.*)$ /index.php?s=$1 将所有非真实文件/目录请求转给 index.php,并把原始路径作为 s 参数传入(ThinkPHP 默认识别 s 为 PATH_INFO 入口)
- last 表示内部重定向,不暴露 index.php 到浏览器地址栏
- 不用 break,否则子请求不重新匹配 location,index.php 会被当作静态文件返回
⚠️ 注意:
- 不要加 if (!-d $request_filename) 或重复判断目录 —— HestiaCP 的基础配置已处理静态资源
- 不要写 rewrite ^/(.*)$ /index.php/$1 —— 这种格式在 HestiaCP 的 fastcgi 环境下会导致 PATH_INFO 解析错乱
- 如果项目入口不在根目录(比如在 /public),需同步修改 root 和 index.php 路径,但绝大多数 ThinkPHP 6+ 项目已将入口放在 public/,此时规则应改为:rewrite ^(.*)$ /public/index.php?s=$1 last;
ThinkPHP 端必须启用的配置项
仅服务端规则生效还不够,ThinkPHP 自身必须明确告诉框架「当前走的是 PATH_INFO 模式」,否则它会 fallback 到 QUERY_STRING(?s=xxx)解析,导致路由不匹配:
立即学习“PHP免费学习笔记(深入)”;
-
'url_route_on' => true—— 必须开启路由(config/app.php) -
'url_html_suffix' => 'html'—— 可选,但建议设为''(空字符串)避免后缀干扰 -
'url_common_param' => false—— 关闭普通参数模式,强制走路由 -
'url_pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'PATH_INFO']—— 显式声明从哪些环境变量取 PATH_INFO(HestiaCP + Nginx 下常用ORIG_PATH_INFO)
特别注意:
- ThinkPHP 6.3+ 默认不再自动识别 s 参数,所以必须配合上面的 rewrite ... ?s=$1 规则 + url_pathinfo_fetch 配置,二者缺一不可
- 若你用的是 ThinkPHP 5.1,请确认 config.php 中有 'URL_MODEL' => 2(PATHINFO 模式)
验证与排错要点
保存 HestiaCP 设置后,务必执行:
- 在面板中点击「Restart Web Server」(不是 reload)
- 清除浏览器缓存或用隐身窗口测试,避免 301 重定向残留
快速验证是否成功:
- 访问 https://yoursite.com/,看首页是否正常(排除基础 rewrite 失败)
- 访问一个已定义的路由,例如 https://yoursite.com/test/hello(对应 Route::rule('test/hello', 'index/test/hello')),观察是否 200 且输出正确内容
- 查看 PHP 日志:tail -f /var/log/php*-fpm.log,出现 Primary script unknown 说明 SCRIPT_FILENAME 路径错误;出现空白响应但无报错,大概率是 PATH_INFO 未被捕获
最易忽略的一点:
HestiaCP 的「PHP Version」设置和「Web Template」模板是解耦的。即使你在域名页选了 PHP 8.2,若「Web Template」仍为默认的 nginx-php74,实际运行的仍是 PHP 7.4 —— 务必进入「Web Templates」检查并同步更新模板,否则高版本 ThinkPHP 会因语法不兼容直接报错退出。



















