symfony 2 中需通过路由 host 条件匹配子域名、自定义 hostbasedexceptionlistener 按 host 动态渲染不同 404 模板,并确保 web 服务器透传 host 头及模板路径适配,才能实现 admin.example.com、api.example.com 等子域名独立 404 页面。

Symfony 2 子域名项目中,404 页面默认由主应用统一处理,但若希望不同子域名(如 admin.example.com、api.example.com)返回各自独立的 404 页面(含不同样式、文案、跳转逻辑),需在路由层与响应层协同配置——不是简单替换模板,而是让 Symfony 按 Host 头识别请求来源,并触发对应错误处理流程。
按子域名匹配路由并隔离错误页面路径
在 app/config/routing.yml(或 routing_dev.yml)中,为每个子域名定义专属路由集,并启用 host 条件约束:
- 使用
host选项限定路由生效范围,例如:admin_routes:<br> resource: "@AppBundle/Controller/AdminController.php"<br> type: annotation<br> host: "admin.{domain}"<br> defaults: { domain: "example.com" } - 确保所有子域名路由都带
host,避免 fallback 到主路由导致 404 被全局捕获 - 不建议用通配符
*.example.com直接匹配全部子域;应显式声明关键子域,便于后续差异化处理
自定义异常监听器按 Host 返回不同 404 响应
Symfony 2 不支持原生多模板 404,需通过事件监听器接管 kernel.exception 事件,在异常发生时根据 Request::getHost() 动态选择模板:
- 创建服务类
App\EventListener\HostBasedExceptionListener,监听kernel.exception - 在
onKernelException方法中判断:
– 若$event->getException() instanceof NotFoundHttpException
– 且$request->getHost()匹配admin.example.com→ 渲染AppBundle:Exception:admin_404.html.twig
– 否则走默认TwigBundle:Exception:error404.html.twig - 在
app/config/services.yml中注册该监听器,优先级设为10以上,确保早于默认异常处理器执行
确保 Web 服务器正确传递 Host 头
Nginx 或 Apache 若未透传原始 Host,$request->getHost() 将无法识别子域名,导致监听器失效:
- Nginx:确认 server 块中未覆盖
Host头,禁用类似proxy_set_header Host $host;的强制重写(除非明确需要) - Apache:启用
UseCanonicalName Off,并在虚拟主机配置中保留ServerAlias *.example.com - 本地开发用
php app/console server:run时,默认不支持多 Host,建议改用 Nginx + hosts 绑定测试真实行为
模板与静态资源路径适配子域名
独立 404 页面常含子域名专属 Logo、导航或 JS 行为,需注意路径引用不因入口变化而失效:
- 模板中避免硬编码
/css/404.css,改用{{ asset('css/404.css') }},确保 Assetic 或 Twig Asset 正确解析 - 若子域名指向不同部署路径(如
admin.example.com对应/admin/子目录),需在config.yml中为各子域设置templating.assets.base_urls - 可借助
app.request.host在模板中动态加载对应 CDN 域名:{{ 'https://' ~ app.request.host ~ '/img/logo-admin.png' }}











