伪静态不成功主因是服务器规则与框架配置未对齐:Apache需.htaccess+mod_rewrite+AllowOverride All三者同时生效;Nginx必须在server块写规则,并正确传递fastcgi_param PATH_INFO,否则PathInfo路由必404。

伪静态配不成功,90% 是服务器规则和框架配置没对齐,不是 ThinkPHP 本身的问题。 直接上关键点:Apache 要靠 .htaccess + mod_rewrite + AllowOverride All 三者同时生效;Nginx 必须在 server 块里写规则,且 fastcgi_param PATH_INFO 要正确传递,否则 index.php/控制器/方法 这类 PathInfo 路由必然 404。
Apache 下 .htaccess 规则为什么总不生效
常见错误是只放了规则,却忘了两件事:一是 Apache 没启用 mod_rewrite,二是虚拟主机配置里 AllowOverride 不是 All。Linux 下用 sudo a2enmod rewrite 启用模块后必须 sudo systemctl restart apache2(或 service apache2 restart);Windows 下要手动在 httpd.conf 里取消 #LoadModule rewrite_module modules/mod_rewrite.so 的注释。然后检查对应 <directory></directory> 块里是否有 AllowOverride All —— 如果是 None 或 FileInfo,.htaccess 里的 RewriteCond 和 RewriteRule 就会被忽略。
实际使用的 .htaccess 内容应为:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
注意:index.php/$1 中的斜杠方向不能错;如果项目不在根目录(比如部署在 /myapp/),必须加 RewriteBase /myapp/,否则重写会跳到错误路径。
立即学习“PHP免费学习笔记(深入)”;
Nginx 配置里 try_files 和 if 判断哪个更稳
if (!-e $request_filename) 看起来直观,但 Nginx 官方明确不推荐在 location 块中使用 if,尤其搭配 rewrite 时容易触发意外匹配(比如静态资源被误重写)。更可靠的是 try_files 方式:
location / {
try_files $uri $uri/ /index.php?s=$uri&$args;
}
它按顺序检查:先找真实文件 → 再找真实目录 → 最后 fallback 到 index.php 并把原始路径塞进 s 参数。这个写法兼容 TP5/TP6,默认路由模式下无需改框架代码。但要注意:如果你用了 pathinfo_depr 设为 '-' 或其他符号,就得同步调整重写规则里的分隔逻辑,否则 index.php/user-login 这种写法会解析失败。
为什么 /index.php/index/index 能访问,但 /index/index 就 404
这是典型的 PathInfo 解析失败信号。Nginx 默认不自动拆解 index.php/xxx 后面的部分,必须显式告诉 PHP-FPM 怎么提取 PATH_INFO。检查你的 Nginx 配置中处理 PHP 的 location ~ \.php$ 块里有没有这两行:
fastcgi_split_path_info ^(.+\.php)(/.+)$;fastcgi_param PATH_INFO $fastcgi_path_info;
缺一不可。漏掉 fastcgi_split_path_info,$fastcgi_path_info 就是空的;漏掉 fastcgi_param,PHP 收不到 $_SERVER['PATH_INFO'],ThinkPHP 自然无法路由。另外确认 PHP 配置中 cgi.fix_pathinfo=1(默认开启,但某些 Docker 镜像或安全加固环境会关掉)。
宝塔面板里选“ThinkPHP”伪静态规则却还是 404
宝塔内置的规则本质就是复制粘贴上面的 Nginx 片段,但它不会帮你检查三件事:root 是否指向 public 目录、PHP 版本是否与 ThinkPHP 兼容(如 TP6.3 要求 PHP >=7.2)、以及站点配置里是否误启用了「防跨站攻击」导致 PATH_INFO 被截断。最简单的验证方式:临时在入口 index.php 开头加一行 var_dump($_SERVER['PATH_INFO'] ?? 'MISSING');,访问 /index/index,如果输出 MISSING 或空字符串,问题一定出在 Nginx 的 fastcgi_param 传递环节,而不是规则本身。
真正卡住人的地方,从来不是规则怎么写,而是哪一层悄悄屏蔽了 PATH_INFO —— 可能是 Nginx 配置、PHP 设置、宝塔开关,甚至 CDN 回源时把路径给抹了。逐层打日志比反复换规则更有效。



















