根本原因是服务器将真实静态文件转发给了index.php,而ThinkPHP不处理;Apache需用RewriteCond !-d和!-f排除目录与文件,Nginx应分层配置location优先匹配静态资源后缀和目录,再fallback至/index.php?$query_string,且root必须指向public/目录。

静态资源加载失败,根本原因不是伪静态规则写错了,而是服务器把真实存在的 CSS、JS、图片等文件也转发给了 index.php,而 ThinkPHP 不处理这些请求,直接返回 404。
Apache 下:用 RewriteCond 排除真实文件和目录
确保 .htaccess 放在 public/ 目录(即 index.php 所在位置),内容如下:
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
关键点:
-
!-d排除真实目录(比如/static/或/uploads/) -
!-f排除真实文件(比如/static/css/app.css) - 两个条件必须同时满足,缺一不可
- 检查 Apache 配置中对应虚拟主机的
AllowOverride是否设为All或至少FileInfo Options
Nginx 下:优先匹配静态资源,再 fallback 到 PHP
不要只靠一个 location / 做兜底。推荐分层配置,顺序很重要:
立即学习“PHP免费学习笔记(深入)”;
先拦截常见静态后缀(放在 location / 之前):
location ~* \.(?:css|js|png|jpe?g|gif|webp|woff2?|ttf|eot|mp4|pdf)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
再拦截整个静态目录(如项目用 /static/ 存资源):
location ^~ /static/ {
alias /www/wwwroot/myapp/public/static/;
expires 1y;
add_header Cache-Control "public, immutable";
}
最后才是主路由规则:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
注意:
- 所有
location必须写在同一个server块内 -
root指令必须指向public/目录,不是项目根目录 - 如果部署在二级目录(如
/myapp/),try_files的第三项要改为/myapp/index.php?$query_string
通用排查要点
很多问题其实出在基础配置上,而非规则本身:
- 确认 Web 根目录是
public/,不是项目根目录(这是 80% 的 Nginx 404 真正原因) - 检查浏览器开发者工具 Network 标签页,看 404 请求的真实路径是否带多余前缀(比如
/public/static/xxx.css),说明 root 设置错误 - 用
curl -I http://yoursite/static/test.png测试响应头,确认是否返回 200 且无X-Powered-By: PHP - ThinkPHP 自身无需额外设置放行静态资源——这事完全由 Web 服务器决定



















