ThinkPHP 6部署时Web服务器根目录必须设为public目录,否则静态资源必然404;因所有请求须经public/index.php统一入口处理,且静态文件实际位于public/下,若根目录设错,服务器将无法定位真实路径。

public目录没设成Web根目录,所有静态资源必然404
ThinkPHP6强制要求所有HTTP请求必须经由public/index.php入口统一处理,静态资源(CSS/JS/IMG)也必须放在public/下,并且Web服务器必须把public/设为实际的网站根目录。如果宝塔或Nginx把站点根目录设成了项目根(比如/www/wwwroot/myapp),那浏览器请求/static/css/app.css时,服务器会在/www/wwwroot/myapp/static/css/app.css找——而真实路径是/www/wwwroot/myapp/public/static/css/app.css,自然404。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 宝塔中:网站 → 设置 → 网站目录 → “运行目录”选
/public(不是留空,也不是/) - Nginx手动配置:确保
root指令指向public的父目录,例如root /www/wwwroot/myapp/public;(注意末尾无斜杠) - Apache用户:确认
DocumentRoot直接指向/www/wwwroot/myapp/public,而非上层目录 - 改完必须重启Web服务,用
curl -I http://localhost/static/test.png验证响应头是否含X-Powered-By: ThinkPHP
用了强制路由(url_route_must=true)却没放行静态路径
开启'url_route_must' => true后,ThinkPHP会拦截所有请求,只放行显式注册的路由。此时/static/xxx.css这类路径不会被自动识别为静态文件,而是当作动态URL去匹配路由——没定义就直接返回404,连Web服务器的文件系统都不碰。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 在
app/route/app.php最顶部加别名:Route::alias('static', 'static');(同理可加css、js) - 更可控的方式是显式匹配后缀:
Route::rule(':path^.*\.(js|css|png|jpg|gif|woff2|ttf)$', 'static/:path', 'GET', ['ext' => '']); - 这两类规则都必须放在
Route::get()、Route::resource()等业务路由之前 - 删掉
runtime/cache/route.php和runtime/route/整个目录,避免缓存干扰
Nginx location配置错位,静态请求被PHP入口吞掉
常见错误是只配了全局try_files,但没给静态路径单独设location块。结果/static/app.css被try_files $uri $uri/ /index.php?$query_string;兜底到public/index.php,再由TP6路由系统处理——而它根本不是路由,最终还是404。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 为静态资源单独写
location ^~ /static/(用^~保证前缀优先级高于正则) - 里面用
root /www/wwwroot/myapp/public;(不是alias),这样/static/css/a.css会映射到/www/wwwroot/myapp/public/static/css/a.css - 务必检查是否有冲突的
location ~* \.(js|css|png)$ { try_files $uri =404; }——这种配置会绕过PHP,导致上面的Route::alias()完全失效 - 用
nginx -T | grep -A5 "location /static"确认配置已加载
CDN回源路径漏了/public前缀
本地能访问/static/app.css,CDN上全404,大概率是CDN回源时没补/public。比如CDN请求https://cdn.example.com/static/app.css,回源地址设成https://origin.example.com,那服务器收到的就是GET /static/app.css,而它只认/public/static/app.css。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- CDN控制台里找“回源路径前缀”或“URL重写”,填
/public - 或者把回源Host设为
origin.example.com,回源协议设为HTTP,再配合Nginx的location /public/重写兜底 - 别依赖
asset()函数自动加public——它只在Web根正确时才可靠;部署前先确认$_SERVER['DOCUMENT_ROOT']是否指向public目录
真正卡住人的从来不是哪条命令没敲对,而是你不确定当前这个404到底是Web服务器返回的,还是ThinkPHP返回的,抑或是CDN中间截的。先用curl -I看响应头里的Server和X-Powered-By,再决定下一步查哪层。



















