生产环境自定义错误页不生效,需确保模板位于templates/bundles/twigbundle/exception/目录下并按error404.html.twig等规范命名,同时清空--env=prod缓存、确认app_env=prod且debug=false已生效。

生产环境自定义错误页不生效?检查模板路径和缓存
Symfony 生产环境默认只渲染 templates/bundles/TwigBundle/Exception/error.html.twig,而不是你放在 templates/error.html.twig 或 templates/bundles/TwigBundle/Exception/error404.html.twig 的文件。它严格按 HTTP 状态码匹配模板名,且必须位于正确路径下。
常见失效原因:
- 模板文件名写成
error404.html.twig但没放在templates/bundles/TwigBundle/Exception/目录下 - 清缓存时漏掉
--env=prod参数,或用了--no-debug却没同步更新环境配置 - APP_ENV=prod 但某些配置仍残留 dev 模式行为(比如
debug: false没在config/packages/prod/twig.yaml中显式设为 false)
验证方式:手动访问 /_error/500(开发环境)和真实触发 500 的路由(生产环境),对比响应内容是否一致。
如何按状态码区分渲染不同错误页?用 TwigBundle 的命名约定
Symfony TwigBundle 内置了按状态码自动匹配模板的逻辑,不需要写 PHP 代码或监听器。只要模板存在且路径正确,框架会自动选中。
支持的命名格式(全部小写,带状态码):
-
error404.html.twig→ 匹配所有 404 -
error500.html.twig→ 匹配所有 500 类错误(如Internal Server Error) -
error.html.twig→ 兜底模板,匹配任何未明确指定的状态码
注意:error404.json.twig 这类扩展名不会被自动识别;若需 JSON 错误响应,应通过 ErrorRendererInterface 实现自定义渲染器,而非依赖模板命名。
想记录异常到数据库?别用全局 try-catch,改用 KernelEvent
在控制器里零散加 try/catch 不仅难维护,还会绕过 Symfony 的异常处理链,丢失上下文、日志通道和 HTTP 状态码语义。正确做法是监听 kernel.exception 事件。
实操要点:
- 创建服务并标记为
kernel.event_listener,优先级设为20以上确保早于默认处理器执行 - 在监听方法中获取
$event->getThrowable(),可安全写入 DB(注意事务已回滚,勿在同事务内操作) - 不要调用
$event->setResponse()干预渲染流程,除非你完全接管错误页——否则会跳过ErrorRenderer和环境适配逻辑
示例判断:若抛出的是 AccessDeniedException,你可能只想记日志不入库;若是 UnexpectedValueException,才触发告警表插入。
开发环境堆栈信息泄露?不是代码问题,是 APP_ENV 配置不对
看到完整源码行、变量 dump、甚至“Debug”按钮,说明当前实际运行环境仍是 dev,哪怕你改了 .env 文件也没用——因为 APP_ENV 在 Web 服务器启动时就被读取并固化了。
排查步骤:
- 确认
public/index.php中是否硬编码了$_ENV['APP_ENV'] = 'dev'(旧项目常见) - 检查 Web 服务器(Nginx/Apache)是否通过
SetEnv或fastcgi_param强制设为 dev - 运行
php -r "var_dump($_SERVER['APP_ENV'] ?? 'not set');"验证真实值
真正起作用的是运行时环境变量,不是 .env 文件内容,也不是 cache:clear 命令本身。











