web服务器root必须指向public目录,否则/static等静态资源请求将404;验证方法是确保http://localhost/app/config.php返回404,且asset()函数生成的路径正确。

Web 服务器 root 必须指向 public 目录
ThinkPHP6 的静态资源(CSS/JS/图片)默认放在 public/static/ 下,但浏览器能访问到的前提是:Web 服务器的 root 指向的是 public 目录,而不是项目根目录(含 app、config 的那层)。否则所有 /static/css/app.css 请求都会 404——因为文件实际在 public/static/css/app.css,而服务器却在项目根目录下找 static/css/app.css。
常见错误现象:
- Nginx 配置中
root写成/var/www/myapp(错),应为/var/www/myapp/public(对) - Apache 的
.htaccess放在项目根目录,没启用或没生效,导致请求全进index.php -
phpEnv 或宝塔新建站点时,默认根目录设成项目顶层,没手动改成
public子目录
验证方法:访问 http://localhost/index.php 能打开,但 http://localhost/app/config.php 必须返回 404;如果后者能打开,说明 root 设错,存在严重安全风险。
用 asset() 生成路径,别手拼 /static/
asset() 是 ThinkPHP6 官方推荐的静态资源 URL 生成函数,它不依赖配置、不扫描文件,只做一件事:拼接当前域名 + 你传入的相对路径。所以它快、稳定,且天然适配子目录部署(只要 base path 正确)。
使用要点:
- 模板中写
{{ asset('static/css/app.css') }},不是/static/css/app.css,更不是{{ asset('public/static/css/app.css') }} - PHP 逻辑里不能用
Url::build(),它专用于路由,不处理静态资源 - 如果把资源挪到
public/assets/,就写asset('assets/js/main.js'),前缀永远不带public/ - Linux 下注意大小写:
Static≠static,路径错一个字母就是 404
Nginx/Apache 必须绕过 PHP 直接服务静态文件
ThinkPHP 的路由层(Route)不负责静态文件分发,那是 Web 服务器的事。把 /static/ 请求塞进路由规则,要么 404,要么让 PHP 去读文件再输出——既慢又浪费资源,还可能暴露路径。
正确做法是让 Nginx/Apache 在 PHP 入口前就命中并返回:
- Nginx:用
alias(不是root)精确映射,且location ^~ /static/必须放在所有~ \.php$规则之前 - Apache:在
RewriteRule ^(.*)$ index.php/$1 [L]前加三行判断:RewriteCond %{REQUEST_FILENAME} !-f、RewriteCond %{REQUEST_FILENAME} !-d、RewriteCond %{REQUEST_URI} !^/static/ - 开发时用
php -S:必须配router.php手动拦截,否则内置服务器根本不会查public/下的文件
CDN 或子目录部署时,asset() 还管用吗?
管用,但得靠外部控制前缀。ThinkPHP6 本身不内置 CDN 开关,asset() 只拼路径,不加协议、不加域名。所以你要么:
- 在
.env里设ASSET_PREFIX=https://cdn.example.com,然后在模板中写{{ asset('static/css/app.css')|raw|replace('https://', ASSET_PREFIX) }}(需自定义过滤器) - 更常用的是模板替换:在
config/view.php的tpl_replace_string中定义'{__STATIC__}' => $_ENV['ASSET_PREFIX'] ?? '/static',然后模板里统一用{__STATIC__}/css/app.css - 子目录部署(如
/myapp/)时,asset()默认不识别前缀,需在public/index.php显式设置$_SERVER['SCRIPT_NAME'] = '/myapp/public/index.php',否则生成的 URL 仍缺前缀
最容易被忽略的一点:改完任何配置(Nginx、.env、view.php),都必须清空 runtime/cache/ 和 runtime/log/,否则旧路径缓存会持续生效,让你以为配置没起作用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











