ThinkPHP/Laravel伪静态失败主因是入口路径、路由模式与Nginx规则不匹配:TP6/8需指向/public/index.php并传s=$1参数、用last跳转、运行目录设为/public;Laravel则用try_files或rewrite指向/public/index.php且不带?s=,同时禁用putenv/ini_set并重载Nginx。

你在宝塔面板里部署了 ThinkPHP、Laravel 或其他 PHP 框架,但访问页面时 URL 仍带 index.php 或直接 404,说明伪静态规则没拼对——不是选个模板就完事,得按框架入口路径、路由模式、Nginx 执行顺序三者严丝合缝地组合规则。
确认框架类型与入口位置
先打开项目根目录,看 public/ 文件夹是否存在。如果存在且 index.php 在 public/ 下(如 ThinkPHP 6/8、Laravel),【伪静态目标必须指向 /public/index.php,而不是根目录的 index.php】;如果 index.php 就在网站根目录(如 ThinkPHP 5.1、Typecho),则规则写 /index.php 即可。错位会导致所有请求 404,且错误日志里只显示 “No input file specified”,不提示路径问题。
再查框架配置:ThinkPHP 看 config/app.php 中 url_model 值,Laravel 看 APP_URL 和 RouteServiceProvider 中的 $asPrefix 是否启用子目录路由。不同值对应完全不同的参数传递方式,不能混用。
ThinkPHP 6/8 PATHINFO 模式规则拼接
这是当前主流部署方式,规则必须同时满足三项:重写非真实文件请求 + 指向 public 入口 + 传 s= 参数 + 使用 last 跳转。
立即学习“PHP免费学习笔记(深入)”;
方法一:宝塔「伪静态」文本框中粘贴(推荐)
if (!-e $request_filename) { rewrite ^(.*)$ /public/index.php?s=$1 last; }
方法二:进「配置文件」手动插入 location 块(更稳,避免 if 被 location ~ \.php$ 拦截)
① 在 server 块内、location ~ \.php$ 之前添加:
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /public/index.php?s=$1 last;
}
}
② 同时确保站点「运行目录」设为 /public(不是留空,也不是 /)
③ 检查 PHP 设置中「禁用函数」未勾选 putenv 和 ini_set —— TP6 启动时靠它们注入 PATH_INFO 配置,勾了就报 URL pathinfo not supported
Laravel 标准模式规则拼接
Laravel 不依赖 s= 参数,而是靠 $_SERVER['REQUEST_URI'] 或 QUERY_STRING 交由 index.php 解析,所以规则里不能带 ?s=,否则路由全失效。
方法1:用 try_files(Nginx 官方推荐,性能更好)
location / {
try_files $uri $uri/ /public/index.php?$query_string;
}
方法2:用 if + rewrite(兼容旧 Nginx 版本)
if (!-e $request_filename) { rewrite ^(.*)$ /public/index.php last; }
【注意:末尾必须是 last,不能是 break;rewrite 目标必须含 /public/,漏掉就 404】
保存后务必点击「重载 Nginx」,仅保存不生效。
多应用或子目录部署的规则补丁
如果你的 ThinkPHP 项目有 admin、api、home 三个应用,且 URL 是 /admin/login、/api/v1/user,那么单条 ^(.*)$ 规则会把 /admin/login 当作整个 s=admin/login 传入,框架无法识别应用前缀。
必须拆成两段捕获:
if(!-e $request_filename) {
rewrite ^/([a-z0-9A-Z_\-]+)/(.*)$ /public/index.php?s=$1/$2 last;
rewrite ^/(.*)$ /public/index.php?s=$1 last;
}
第一行匹配带应用名的请求(如 /admin/login → s=admin/login),第二行兜底默认应用(如 /login → s=login)。两行顺序不能颠倒,否则 /admin/login 会被第二行先截成 s=/admin/login,应用名丢失。
若部署在子目录(如域名后是 /myapp/),所有 rewrite 的开头路径和目标路径都要加前缀:rewrite ^/myapp/(.*)$ /myapp/public/index.php?s=$1 last;



















