thinkphp 5.0 子目录部署静态资源访问失败的核心原因是web服务器未将根目录设为public且path_info与入口路径不匹配;必须将documentroot/root指向/public子目录,配置rewritebase或nginx location别名,并使用asset()生成路径。

ThinkPHP 5.0 在子目录部署时静态资源访问不到,核心问题不是代码写错了,而是 Web 服务器没把请求正确落到 public 目录下的真实文件上,同时 PATH_INFO 和入口路径没对齐。
确认 Web 根目录指向 public 子目录
这是所有问题的前提。ThinkPHP 5.0 要求网站根目录必须是项目中的 public/ 目录,而不是整个项目根目录(含 app、config 等)。如果部署在子目录(比如 http://example.com/myapp/),那服务器实际 DocumentRoot 或 root 必须设为 /var/www/html/myapp/public,不是 /var/www/html/myapp。
- Apache:检查
VirtualHost中DocumentRoot是否带/public,且.htaccess文件就在该目录下 - Nginx:server 块中
root指令值必须以/public结尾,例如root /var/www/html/myapp/public; - 宝塔用户:网站设置 → 「运行目录」必须选
/public,改完点“保存”并重启服务
修正 .htaccess 或 Nginx 伪静态规则
子目录部署时,原生 ThinkPHP 5 的 .htaccess 规则默认按根目录设计,会漏掉子目录前缀,导致 /myapp/static/css/app.css 被当成动态路由处理或直接 404。
- Apache:在
public/.htaccess开头加一行RewriteBase /myapp/(把myapp替换为你的真实子目录名) - Nginx:不能只用通用
try_files,要显式匹配子目录路径。例如部署在/myapp/,就写:location /myapp/ {<br> alias /var/www/html/myapp/public/;<br> try_files $uri $uri/ /myapp/index.php?$query_string;<br> }
注意alias后路径末尾要有/,且内部try_files的重写目标也带/myapp/
模板里用 asset() 生成路径,别硬写
手写 <link href="/static/css/app.css"> 在子目录下必然失效,因为浏览器会去请求 http://example.com/static/...,而实际路径是 http://example.com/myapp/static/...。
- 正确写法:
<link href="%7B%7B%20asset('static/css/app.css')%20%7D%7D"> -
asset()函数自动适配当前部署环境,包括子目录前缀、域名、是否启用 URL 重写 - 传入路径不带
public/前缀,框架默认从public开始找;Linux 下注意大小写,Static/≠static/
检查 PATH_INFO 传递是否完整
子目录部署后,$_SERVER['SCRIPT_NAME'] 应该是 /myapp/index.php,不是 /index.php。如果它被截断,PATH_INFO 就无法正确提取 /myapp/ 后面的路由段,静态资源虽能直出,但后续路由会错乱。
- 在
public/index.php开头加:var_dump($_SERVER['SCRIPT_NAME'], $_SERVER['REQUEST_URI']); die(); - 如果输出中
SCRIPT_NAME不含/myapp/,说明 Apache/Nginx 没透传子目录信息,需检查 rewrite 规则或 fastcgi_param 配置 - Nginx 下确保有:
fastcgi_param PATH_INFO $fastcgi_path_info;
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











