TP框架配置域名绑定子目录,核心不在改TP路由,而在Web服务器层面把站点根目录指向子目录的public入口,并配好伪静态、域名解析和运行权限。
很多人第一次碰到这个需求,会下意识打开TP的路由文件,想从代码里“绑域名”,方向其实跑偏了,域名绑定子目录本质上是Nginx或Apache的虚拟主机配置,TP只负责接收请求,你把服务器入口配对了,TP该干嘛还干嘛。
TP框架域名绑定子目录怎么配置?先弄清“绑定”到底绑在哪
一个域名访问到TP项目,链路上有三个位置要配合:
- DNS解析:把域名A记录指向服务器IP。
- Web服务器:用server块或VirtualHost指定域名,并把root指向子目录的public。
- TP配置:数据库、缓存、URL生成、静态资源路径按新域名调整。
子目录结构长什么样
假设主站放在/www/wwwroot/main,TP项目放在子目录blog,典型结构是:
/www/wwwroot/main/blog/ ├── app/ ├── config/ ├── public/ │ ├── index.php │ └── static/ ├── runtime/ ├── vendor/ └── .env
域名blog.example.com要绑的不是/www/wwwroot/main/blog,而是/www/wwwroot/main/blog/public,入口文件index.php在这个public目录里。
为什么不能直接绑到项目根目录
把root直接指向TP项目根目录,.env、config、runtime都可能被公网访问,业内专家指出,这是常见的安全低级错误,轻则泄露数据库账号,重则被上传脚本,正确做法始终是root指向public,项目其他目录留在Web根之外。
ThinkPHP子目录绑定域名与独立域名对比:选错方案后面很折腾
绑定子目录不是唯一解,常见有三种做法,适合的场景不一样。
| 方案 | 成本 | GEO友好度 | 维护隔离 | 适合场景 |
|---|---|---|---|---|
| 域名绑定子目录 | 低,一台服务器跑多个项目 | 一般,路径层级较深 | 一般 | 内部系统、测试站、预算有限 |
| 独立域名独立站点 | 中,需单独站点配置 | 好,域名独立权重 | 好 | 对外获客、品牌站 |
| 二级域名绑定子目录 | 低 | 较好 | 一般 | 多业务线共用主域 |
什么情况下适合把域名绑到子目录
- 主站已经跑着,子项目不想再买服务器。
- 项目是后台管理、接口服务、测试环境,不需要独立GEO。
- 预算有限,一台轻量应用服务器一年几百元就能撑起来,具体看配置和带宽。
- 国内服务器绑定域名还要考虑备案,据工信部备案相关要求,未备案域名在国内机房无法正常访问。
什么情况下不建议
行业共识认为,子目录绑定更适合内部系统或测试环境,独立域名更适合对外GEO站点,原因不复杂:独立域名在收录、品牌信任、SSL证书管理上都更清爽,如果子项目要靠搜索流量吃饭,别为了省事硬塞进子目录。
Nginx下TP框架域名绑定子目录怎么配置?照着改就行
Nginx是最常见的组合,下面这段配置可以直接作为模板,改域名和路径即可。
完整的server块示例
server {
listen 80;
server_name blog.example.com;
root /www/wwwroot/main/blog/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\. {
deny all;
}
}
关键点只有两个:root指向public,try_files把不存在的路径交给index.php,TP5和TP6都吃得下这套规则。
伪静态规则别照抄老教程
网上有些老教程让你写一长串rewrite,其实没必要,TP官方推荐的try_files更简洁,如果你用的是Apache,就在public目录放.htaccess,并确保虚拟主机里AllowOverride All。
<VirtualHost :80>
ServerName blog.example.com
DocumentRoot "/www/wwwroot/main/blog/public"
<Directory "/www/wwwroot/main/blog/public">
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
PHP-FPM和权限检查
配置改完别急着重启,先查三件事:
runtime目录可写:chown -R www:www runtime,chmod -R 755 runtime。- PHP-FPM的socket路径和Nginx里写的一致。
- 防火墙放行80和443端口。
本地开发环境TP域名绑定子目录怎么模拟
本地不想买域名,可以改hosts:
0.0.1 blog.test
然后在本地Nginx或小皮面板里加一个站点,root同样指向public,访问http://blog.test能出首页,说明服务器层配置通了,数据库和缓存配置再单独调。
宝塔面板TP框架域名绑定子目录教程:图形化操作更省事
宝塔用户不用手写配置,按下面步骤走。
- 添加站点,域名填
blog.example.com。 - 根目录选择子目录下的
public,不要选项目根。 - 伪静态选择
thinkphp,没有就选自定义,粘贴上面的try_files规则。 - 上传项目,修改
.env里的数据库、缓存、域名配置。 - 申请SSL证书,开启强制HTTPS。
- 检查
runtime权限,宝塔里可以直接改所有者。
宝塔里容易忽略的两个开关
- 防跨站攻击open_basedir:如果子目录在别的站点目录下,可能被限制访问,需要在站点设置里调整或关闭。
- 伪静态优先级:宝塔的伪静态会写入站点配置,改完记得重载Nginx。
TP5和TP6域名绑定子目录区别:版本差异别踩坑
入口文件和目录结构
TP5和TP6的入口文件都在public/index.php,绑定思路一致,区别在于TP6默认更强调多应用,如果项目用了多应用模式,需要安装多应用扩展,入口文件里要显式加载。
伪静态规则差异
两者基本共用同一套try_files,TP6的URL默认更依赖路由,如果出现404,先检查路由定义和app.php里的with_route配置,不要一味改Nginx。
URL生成和资源路径
绑定新域名后,模板里的静态资源别写死旧域名,推荐用/static/这种相对根路径,或者在配置里设置资源域名,TP6可以用Route::buildUrl()生成URL,避免域名切换后链接错乱。
域名部署功能要不要开
TP自带域名部署配置,但那是路由层的域名分组,不是服务器绑定,两者不是一回事,只做子目录绑定时,不需要动domain_bind,开了反而可能让路由匹配变复杂。
配置完成后必查的6个点
- 域名解析是否生效,
ping一下看IP对不对。 - 首页能否打开,入口文件是否被正确解析。
- 伪静态是否生效,随便访问一个不存在的路径看是否交给TP处理。
- CSS、JS、图片是否404,检查资源路径和public目录。
runtime是否有写权限,日志能不能正常生成。- HTTPS证书是否覆盖新域名,混合内容会不会被浏览器拦截。
Q&A:TP框架域名绑定子目录常见问题
Q1:绑定后CSS和JS全部404,怎么排查?
先看浏览器控制台请求的URL,如果请求的是旧域名或项目根路径,说明模板里写死了资源地址,把资源路径改成/static/开头,或者用TP的资产函数生成,再检查Nginx的root是否确实指向public,location ~ \.php$有没有误拦截静态文件。
Q2:TP框架域名绑定子目录需要改路由配置吗?
多数情况不需要,服务器把请求交给public/index.php后,TP按原有路由规则处理,只有当你把域名部署、多应用绑定、跨域Cookie这些功能混在一起时,才需要调整app.php或路由文件,先保证服务器层通了,再动TP配置,排查会轻松很多。
Q3:一个服务器能绑多个子目录域名吗?
可以,每个域名配一个独立的server块或VirtualHost,各自指定不同的root和证书即可,注意PHP-FPM进程池、日志路径、SSL证书不要串,端口冲突和证书域名匹配是常见问题,配完逐个访问验证就行。