关键在于统一域名识别逻辑:禁用app_host等环境依赖配置,启用url_domain_deploy,本地通过hosts+泛域名nginx配置(server_name *.example.com)使http_host与线上一致,并确保fastcgi_param http_host $http_host;正确传递。

ThinkPHP配置二级域名要让Linux服务器和本地环境行为一致,关键不是写两套配置,而是统一识别逻辑、屏蔽环境差异。核心在于:框架靠$_SERVER['HTTP_HOST']判断域名,而本地常用localhost或127.0.0.1,这些根本不会匹配线上域名规则,导致路由直接 fallback 到默认应用。
统一域名识别入口:禁用环境依赖配置
别碰app_host——它只在命令行(CLI)下生效,Web 请求中完全被忽略。真正起作用的是域名绑定开关和路由规则:
- 确保
config/app.php中启用'url_domain_deploy' => true(TP6)或'APP_SUB_DOMAIN_DEPLOY' => 1(TP5/3.2) - 删除所有基于
APP_ENV或php_sapi_name()做的条件判断配置,比如“本地用www.test.com,线上用www.example.com”这类写法 - 不使用
domain_bind.php硬编码完整域名(如['admin.example.com' => 'admin']),因为它在本地无法命中,且TP5.1不支持运行时变量
本地开发用泛解析+Hosts模拟真实域名
Windows/macOS/Linux都可通过修改hosts文件 + Nginx/Apache泛匹配,让本地请求携带真实子域名 Host 头:
- 在
/etc/hosts(macOS/Linux)或C:\WINDOWS\system32\drivers\etc\hosts(Windows)中添加:127.0.0.1 admin.example.com127.0.0.1 api.example.com127.0.0.1 example.com - Nginx 配置
server_name支持通配:server_name *.example.com example.com;
这样所有*.example.com请求都会进同一入口,PHP 才能拿到HTTP_HOST = admin.example.com - Apache 对应配置:
ServerAlias *.example.com
路由绑定推荐显式+泛域名兜底组合
避免依赖 DNS 后缀判断(如APP_DOMAIN_SUFFIX),直接按子域名字符串匹配最可靠:
- TP6 写法(
app/route.php):Route::domain('admin', function () { ... });Route::domain('api', function () { ... });Route::domain('*', function () { ... }); // 兜底,处理未声明的子域名 - TP5.1 或需动态商户名场景:改用中间件解析,不依赖静态配置
写一个SubDomainParseMiddleware,在$request->host()中提取第一段(如shop1),存为$request->withParam('sub_domain', 'shop1'),控制器里直接读取 - 多应用模式下(
app/admin/,app/api/),用Route::domain('admin', 'admin')即可,无需额外控制器命名空间调整
Nginx配置必须传递原始Host头
很多线上404其实卡在Nginx没把Host头传给PHP,尤其用了反向代理或CDN后:
- 确认
fastcgi_params中包含:fastcgi_param HTTP_HOST $http_host;fastcgi_param SERVER_NAME $server_name; - root 必须指向项目
public/目录,不是某个模块目录;入口始终是public/index.php,由框架内部分发 - 不要为每个子域名单独建
server块再指不同入口文件(如admin.php),这会破坏统一入口机制,导致Request::domain()失效
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











