ThinkPHP 5 域名绑定必须在 route/app.php 中用 Route::domain() 定义,仅匹配 $_SERVER['HTTP_HOST'],需 Web 服务器正确传递 Host 头并配置重写规则,本地开发须配 hosts 文件且禁用 php -S。

ThinkPHP 5 的域名绑定和重写规则是两件事,不能混用;域名绑定靠 Route::domain() 在 route/app.php 中定义,重写规则靠 Web 服务器(Apache/Nginx)配置,二者缺一不可,且各自有关键约束。
Route::domain() 必须写在 route/app.php,其他位置无效
很多人把域名路由塞进 config/route.php、app/middleware.php,甚至控制器里调用 Route::domain(),结果请求始终 404。原因很直接:ThinkPHP 5 的域名匹配发生在路由解析最前端,只识别 route/app.php 中注册的规则。
-
route/route.php是闭包路由专用文件,不支持Route::domain() - 多应用模式下(如
app/admin/),域名绑定仍统一写在route/app.php,不能按应用拆分 - 若用了
APP_SUB_DOMAIN_DEPLOY开关,Route::domain()仅在对应子应用内生效,不会改变全局上下文
本地开发时 HTTP_HOST 不匹配导致域名绑定失效
本地跑 php -S 或访问 localhost:8000 时,$_SERVER['HTTP_HOST'] 是 localhost:8000,而你写的 Route::domain('admin.example.com', ...) 完全不匹配——框架根本不会进入该闭包。
- 必须修改系统
hosts文件,添加127.0.0.1 admin.example.com - Web 服务器需配置对应
ServerName(Apache)或server_name(Nginx) - 开发环境推荐加判断:
if (env('APP_DEBUG')) { Route::domain('localhost', [...]); },避免每次改 hosts - 别用
php -S测试域名绑定,它不透传HTTP_HOST,Route::domain()永远不触发
重写规则不等于域名绑定,.htaccess 或 Nginx 配置必须到位
url_domain_deploy 和 url_html_suffix 这类配置只影响 URL 生成逻辑(比如 url() 函数输出什么),跟服务器是否能去掉 index.php 完全无关。真正起作用的是 Web 服务器重写规则。
- Apache 必须启用
mod_rewrite,且对应目录的AllowOverride设为All,不是None -
.htaccess中的RewriteBase必须与项目实际部署路径一致(如项目在/myapp/,就得写RewriteBase /myapp/) - Nginx 的
try_files必须带$query_string,否则 GET 参数丢失:try_files $uri $uri/ /index.php?$query_string; - 百度云 BCH 等虚拟主机不支持改根目录,得在
/webroot/index.php中手动引入./public/index.php,再配 Nginx location 规则
域名绑定 + 重写共存时容易忽略的细节
当同时启用域名绑定和 URL 重写时,有两个隐性依赖常被跳过,导致 500 或静默 fallback:
- Nginx 必须显式传递
HTTP_HOST:fastcgi_param HTTP_HOST $http_host;,否则Route::domain()拿不到原始 Host - 如果用了泛域名(如
*.example.com),TP5 不原生支持,得靠 Nginx server 块做泛匹配,再由框架根据HTTP_HOST字符串判断 -
php think route:list默认只显示主域名下的路由,子域名规则不会列出来,调试时要用var_dump(Route::getRules())查看完整数组 - 多个
Route::domain()注册相同路径(如都定义admin/),后注册的会被前一个吞掉,框架不校验域名是否真实命中
真正卡住人的从来不是语法,而是 HTTP_HOST 是否被正确传递、重写是否真生效、以及本地 hosts 和 server 配置有没有对齐——这三处任一缺失,Route::domain() 就只是段死代码。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











