必须通过web服务器(nginx/apache)配置独立server块或virtualhost,使frontend和backend分别指向各自web目录并隔离cookie/session路径,否则会因入口文件执行错位、session冲突和asset错乱导致404或登录异常。

Yii 框架本身不处理虚拟主机映射,真正起作用的是 Web 服务器(Nginx/Apache)的配置。你不能靠改 urlManager 或加 bootstrap 就让 frontend 和 backend 分开访问,必须让两个应用各自拥有独立的 server 块或 VirtualHost。
为什么 Nginx 的 server 块必须分开配
因为 Yii 高级模板中 frontend/web/index.php 和 backend/web/index.php 是两个完全独立的入口文件,各自加载自己的 $config、Application 实例和组件。Web 服务器决定哪个 index.php 先被执行 —— 这一步发生在 PHP 和 Yii 启动之前。
- 如果只配一个
server,把root指向frontend/web,那访问admin.example.com时请求根本不会进backend/web/index.php,直接 404 或被 frontend 路由拦截 - 若强行用子路径(如
/admin)代理到 backend,会触发 session cookie 冲突:_identity和PHPSESSID的path值混在一起,登录态互相覆盖 -
assets发布也会错乱:frontend 和 backend 的 asset bundle 默认都生成在@webroot/assets下,路径重叠导致 JS/CSS 加载失败
Apache VirtualHost 配置关键点
每个站点需独立 <virtualhost></virtualhost>,且 DocumentRoot 必须精确指向对应 web 目录:
- 前台站点:
DocumentRoot /path/to/project/frontend/web,ServerName www.example.com - 后台站点:
DocumentRoot /path/to/project/backend/web,ServerName admin.example.com - 两个配置里都要启用
mod_rewrite,并确保.htaccess存在且规则正确(尤其RewriteRule ^(.*)$ index.php?$1 [L,QSA]) - 别漏掉
AllowOverride All,否则 rewrite 规则不生效
示例片段:
<virtualhost>
ServerName www.example.com
DocumentRoot "/var/www/myapp/frontend/web"
<directory>
AllowOverride All
Require all granted
</directory></virtualhost><virtualhost>
ServerName admin.example.com
DocumentRoot "/var/www/myapp/backend/web"
<directory>
AllowOverride All
Require all granted
</directory></virtualhost>
backend/config/main.php 的 cookie 和 session 必须隔离
即使 Web 服务器已分站,若 backend 的 session 和 user 组件仍用默认 path,cookie 仍可能被 frontend 读取或覆盖,造成登录跳转异常或权限错乱。
-
'request' => ['csrfCookie' => ['path' => '/admin']]:确保 CSRF token 只在/admin下发送 -
'user' => ['identityCookie' => ['name' => '_identity-backend', 'path' => '/admin']]:避免和 frontend 的_identity冲突 -
'session' => ['name' => 'advanced-backend', 'cookieParams' => ['path' => '/admin']]:强制 session cookie 限定在 admin 域下 - 所有 path 值必须以
/开头,且与 VirtualHost 的ServerName对应路径一致(不是子目录)
常见踩坑:alias 设置和入口文件误改
有人试图在 frontend/web/index.php 里加 Yii::setAlias('@backend', ...),这是危险操作 —— 它会让 autoloader 同时加载两套 model 和 component,vendor 类重复注册,报 Class 'xxx' not found 或 Cannot redeclare class。
-
frontend/web/index.php和backend/web/index.php原样保留,不要修改第13行的(new yii\web\Application($config))->run() - 确认两个入口文件顶部的
YII_ENV设置一致,比如都是prod,否则common/config/main-local.php可能被错误加载 - 不要在
common/config/main.php里写任何 frontend/backend 特定逻辑 —— 它是共享层,只放通用配置
真正的隔离点只有两个:Web 服务器路由 + 应用级 cookie/session path。其他地方动得越少,越稳定。











