CentOS上ThinkPHP伪静态必须区分Apache与Nginx方案:Apache需启用mod_rewrite、AllowOverride FileInfo Options,并将.htaccess置于public目录且含E=PATH_INFO规则;Nginx应禁用fastcgi_split_path_info,用try_files $uri $uri/ /index.php?$query_string,root必须指向public,runtime权限设775并确保Nginx与PHP-FPM用户同组。

CentOS 上 ThinkPHP 伪静态必须分清 Apache 和 Nginx 两套方案,混用或照搬配置会直接导致 404 或 PATH_INFO 错乱——尤其是 TP5/6 默认开启强制路由后,入口文件找不到、参数解析失败是高频问题。
Apache 下 .htaccess 不生效的三个硬性条件
不是写对规则就行,得先满足这三条,否则 RewriteRule 全部被忽略:
-
mod_rewrite模块必须已加载:运行httpd -M | grep rewrite,看到rewrite_module (shared)才算通过 -
AllowOverride必须设为FileInfo Options(不能只写All,也不能漏掉Options);在/etc/httpd/conf/httpd.conf或虚拟主机配置里找对应<Directory>块修改 -
.htaccess文件必须放在public/目录下(不是项目根目录),且 Apache 进程用户(如apache或www-data)有读取权限:ls -l public/.htaccess确认权限至少是644
典型可用规则(TP6 推荐):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1]
</IfModule>
注意:E=PATH_INFO:$1 是关键,TP 依赖它做路由匹配;如果去掉,$_SERVER['PATH_INFO'] 为空,所有带变量的路由(如 user/<id>)全部失效。
立即学习“PHP免费学习笔记(深入)”;
Nginx 的 try_files 写法比 if 判断更稳
很多教程教用 if (!-e $request_filename) { rewrite ... },但在 CentOS 的 Nginx(尤其 1.20+)上容易触发 rewrite or internal redirection cycle 错误,且和 fastcgi_split_path_info 冲突导致 PATH_INFO 错乱。
正确做法是删掉所有 fastcgi_split_path_info 相关行,在 server 块内用:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
这个写法适配 TP5/6 默认路由模式,不依赖 PATH_INFO,也不要求 index.php 后带斜杠,兼容性最强。同时必须确认:root 指向的是 public/ 目录,不是整个项目目录。
runtime 目录权限 755 失败?其实是组没对上
报 mkdir(): Permission denied 在 runtime/log/ 或 runtime/cache/,不是因为权限太低,而是 Nginx worker 进程用户(如 nginx)和 PHP-FPM 进程用户(如 www 或 apache)不属于同一组,导致无法写入。
解决步骤:
- 查 Nginx 用户:
ps aux | grep nginx | grep master看第一列,通常是nginx - 查 PHP-FPM 用户:
ps aux | grep php-fpm | grep master,看user=配置项,常见为www - 把两个用户加进同一组,例如
usermod -a -G www nginx,然后重启nginx和php-fpm -
runtime/目录权限设为775,属主属组设为nginx:www(按实际用户调整)
别信“755 就够了”的说法——CentOS 默认 SELinux 开启时,chown 后还得跑 restorecon -Rv runtime/,否则照样拒绝写入。
宝塔面板里选 thinkphp 模板可能踩坑
宝塔后台「伪静态」选项卡里点选 thinkphp 模板,看似省事,但它默认生成的是 if (!-e $request_filename) { rewrite ... } 写法,和上面说的 Nginx 1.20+ 兼容性差。
更麻烦的是:它不检查你是否把 root 指向了 public/,如果仍指向项目根目录,application/、config/ 就会暴露在 Web 下,等同于裸奔。
建议操作:
- 手动粘贴
try_files规则,而不是选模板 - 在「网站目录」设置页,确认「运行目录」填的是
/public(不是留空或填/) - 部署完立刻用浏览器访问
http://你的域名/config/app.php,如果返回 404 才算安全;如果能下载或显示内容,说明目录权限或 root 设置全错了
最易被忽略的一点:TP6 的 APP_DEBUG = true 时,部分路由错误会直接抛异常页面,掩盖了伪静态未生效的本质;上线前务必关掉调试模式再验证 URL 是否真正走通。



















