CodeIgniter 4.7.2 必须用 $routes->group() 配合 hostname 参数并配置 Nginx/Apache 透传 Host 头才能支持子域名路由;仅改 PHP 路由或仅配反向代理而不设 proxy_set_header Host $host 会导致子域名 404。

CodeIgniter 4.7.2 原生不支持子域名路由自动解析,必须靠 $routes->group() 配合 hostname 选项 + Web 服务器显式转发才能生效;只改 PHP 路由配置而忽略 Nginx/Apache 设置,子域名永远 404。
为什么 $routes->group() 的 hostname 参数必须用
CI4 的路由系统本身不解析 Host 请求头——hostname 是个“守门人”开关:它让该分组下的所有路由仅在匹配指定域名时才参与匹配。不用它,哪怕你在 Nginx 里把 admin.example.com 转发到同一份代码,CI 仍会把请求当成 www.example.com 处理,导致后台路由完全不触发。
-
$routes->group('admin', ['hostname' => 'admin.example.com'], function($routes) { ... });—— 正确:后台只响应 admin.example.com 下的 /dashboard、/users 等路径 -
$routes->get('admin/dashboard', 'Admin::dashboard');—— 错误:这个路由对所有域名都开放,无法隔离前后端入口 - 多个子域名需独立分组:
['hostname' => 'api.example.com']和['hostname' => 'admin.example.com']不能合并,否则路由冲突
Nginx 必须显式传递 Host 头,不能只靠 proxy_pass
很多部署者以为配了 proxy_pass http://127.0.0.1:8080; 就够了,其实 Nginx 默认会重写 Host 为 upstream 地址(变成 127.0.0.1),CI 拿不到原始域名,hostname 判断直接失效。
- 必须加这三行:
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- 若用 Apache,对应的是
ProxyPreserveHost On,且确保mod_proxy已启用 - 本地开发用
php spark serve不支持多 Host,必须切到 Nginx/Apache 才能验证子域名逻辑
前后端同源但路径分离时,别混用 hostname 和 prefix
如果前后端共用一个域名(如 example.com),只是路径不同(/admin/... vs /api/...),就不要强行套 hostname。此时应退回到纯路径分组,并用中间件区分权限域:
$routes->group('admin', ['filter' => 'auth', 'namespace' => 'App\Controllers\Admin'], function($routes) { ... });$routes->group('api', ['filter' => 'api_auth', 'namespace' => 'App\Controllers\API'], function($routes) { ... });- 错误做法:
['hostname' => 'example.com', 'prefix' => 'admin']—— hostname 是全匹配,不是子串匹配,这样写等于禁掉所有请求
子域名路由真正的复杂点不在 PHP 代码,而在 Web 服务器与 DNS 的协同:DNS 解析必须指向同一台机器,Nginx/Apache 必须正确透传 Host,CI 的 hostname 才有判断依据。漏掉任一环,$routes->group() 就只是个摆设。



















