宝塔配ThinkPHP伪静态核心是将非真实文件请求转发至index.php并传s=参数;PATHINFO模式必须用last、禁用putenv需检查、重载Nginx不可省略。

宝塔面板里配 ThinkPHP 伪静态,核心就一条:必须让所有非真实文件的请求,准确转发到 index.php,并把原始路径作为 s=xxx 参数传进去;否则路由解析失败,直接 404。
ThinkPHP 6/8 的伪静态规则要分 PATHINFO 模式还是兼容模式
TP6 默认启用 PATHINFO 模式(url_model = 2),此时 Nginx 规则必须带 s=$1,否则 $_GET['s'] 为空,框架无法识别路由。如果你改过 config/app.php 中的 url_model,比如设为 0(兼容模式)或 1(URL_PATHINFO),规则就得同步调整:
- PATHINFO 模式(推荐且默认):用
rewrite ^(.*)$ /index.php?s=$1 last; - 兼容模式(
url_model= 0):实际走?s=xxx查询参数,规则仍可用上面那条,但需确保 PHP 不过滤s参数 - URL_PATHINFO 模式(
url_model= 1):Nginx 需额外设置fastcgi_split_path_info,宝塔默认不支持,容易出PATH_INFO not supported错,不建议在宝塔上硬刚
在宝塔「伪静态」选项卡里粘贴规则时,last 和 break 不能混用
几乎所有 TP 相关 404 都源于这里。宝塔的「伪静态」文本框最终会写入 Nginx 的 server 块,而规则执行顺序和跳转控制依赖 last 或 break:
-
last:重写后重新匹配 location,确保/index.php?s=xxx能进到 PHP 处理流程 —— 这是必须的 -
break:重写后不再匹配其他 location,/index.php?s=xxx可能被当成静态文件返回源码或 404 - 常见错误写法:
rewrite ^(.*)$ /index.php?s=$1 break;→ 必然失败 - 正确写法(放在伪静态文本框中):
if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; }
多应用模式(如 admin/api/home)要单独加正则捕获应用名
TP6 多应用不是靠子目录自动识别的,得靠伪静态把第一段路径(如 /admin/login 中的 admin)提取出来,拼进 s 参数,否则一律走默认 app 应用:
立即学习“PHP免费学习笔记(深入)”;
- 基础单应用规则不适用,必须替换为两段式重写
- 推荐规则(注意空格和括号):
if(!-e $request_filename) { rewrite ^/([a-z0-9A-Z_\-]+)/(.*)$ /index.php?s=$1/$2 last; rewrite ^/(.*)$ /index.php?s=$1 last; } - 第一行匹配带应用前缀的请求(如
/admin/login→s=admin/login) - 第二行兜底匹配根路径或公共资源(如
/static/css/app.css) - 如果应用名含中文或特殊符号(如
user_v2),正则里的字符集要补全,比如[a-z0-9A-Z_\-]
保存后必须点「重载 Nginx」,且要检查 PHP 是否禁用了 pathinfo
很多人点了保存就以为完事了,其实没生效。宝塔的「保存」只是写入配置文件,不触发重载;而重载失败或部分生效,又常被忽略:
- 保存伪静态内容后,页面右上角会出现「重载 Nginx」按钮,必须点它(不是重启,也不是 reload 命令)
- 验证是否生效:访问一个不存在的真实文件路径,比如
/test-abc123,应返回 TP 路由结果,而不是 404 页面 - 如果仍报
URL pathinfo not supported,去宝塔 PHP 设置 → 禁用函数列表,确认没禁用putenv(它影响 PATH_INFO 解析) - 再检查
phpinfo()页面里Loaded Modules是否有mod_rewrite(Apache)或ngx_http_rewrite_module(Nginx)
真正卡住人的地方,往往不是规则写错,而是 last 写成 break、重载没点、或者 PHP 层面悄悄禁了 pathinfo 支持 —— 这三处查完,90% 的 ThinkPHP 伪静态问题就定位到了。



















