子域名路由匹配失败主因是框架未加载Route::domain()规则:需确保其写在route/app.php顶层、启用url_domain_deploy和route_domain_bind配置、Nginx透传HTTP_HOST并匹配server_name、闭包内重写全部路由且不嵌套。

子域名路由匹配不到,90% 是请求压根没进到 Route::domain() 的匹配逻辑里——不是你写错了,是框架根本没拿到 Host 头,或者压根没加载那条规则。
Route::domain() 没被加载或位置写错了
ThinkPHP5 只认 route/app.php 里定义的域名路由,写在 route/route.php、控制器、中间件甚至 config/route.php 都无效。
-
Route::domain('api.example.com', function () { ... })必须直接放在route/app.php的顶层作用域,不能嵌套在 if 或其他闭包里 - 多应用模式下(
APP_MULTI_MODULE = true),Route::domain()会被跳过,需改用 Nginx 虚拟主机或独立入口文件 - 别把域名路由塞进
Route::group()里,它会变成子组路径,无法响应子域名请求
url_domain_deploy 和 route_domain_bind 配置没开
TP5 默认关闭域名路由识别,两个配置项必须显式启用,且名称不能混淆:
- 必须在
config/app.php中设'url_domain_deploy' => true(影响url()生成带域名链接) - 还必须设
'route_domain_bind' => true(否则Route::domain()规则被静默忽略,连报错都没有) - 注意:
route_domain_bind是 TP5 的键名,url_domain_deploy是 TP5/TP6 兼容项;别写成route_domain_enable或url_route_domain这类不存在的配置
Nginx 没透传 HTTP_HOST,或 server_name 不匹配
Route::domain() 匹配依赖 $_SERVER['HTTP_HOST'],这个值为空、为 localhost 或与配置不一致,就直接跳过。
立即学习“PHP免费学习笔记(深入)”;
- Nginx
server块中必须有server_name api.example.com;,不能只写example.com或泛域名* - 必须在 fastcgi_params 或站点配置中包含:
fastcgi_param HTTP_HOST $http_host;(阿里云/腾讯云默认模板常删掉这行) - 本地测试时,
/etc/hosts(macOS/Linux)或C:\Windows\System32\drivers\etc\hosts(Windows)必须加127.0.0.1 api.example.com - 别用
php -S内置服务器跑子域名——它不支持 Host 头路由,Route::domain()在里面永远不触发
闭包里没重写该域名下的全部路由
Route::domain() 是独立作用域,不继承外部任何路由规则。你原来写的 Route::rule()、Route::resource() 对它完全不可见。
- 必须把所有该子域名需要的路由,全部重新写进闭包里,例如:
Route::domain('api.example.com', function ($r) { $r->get('v1/user', 'api.User/index'); $r->post('v1/user', 'api.User/save'); $r->resource('v1/article', 'api.Article'); }); - 闭包参数是
$r(think\Route实例),别错写成Route::get()(那是静态调用,注册到根域) - 泛域名
Route::domain('*')同样要显式调用$r->get()等,不能只靠Route::rule()
最易被忽略的一点:即使所有配置和代码都对了,php think route:list 默认只显示主域名下的路由,子域名规则不会列出来——得用 var_dump(Route::getRules()) 查看完整数组,确认 domain 键下是否有对应子数组。



















