核心问题是环境切换后缓存未刷新、路由未重新编译或环境配置未生效。需确认APP_ENV值、清空对应缓存、验证路由是否加载、检查入口文件匹配及排除.env干扰。

Symfony 2 中因环境变量切换导致路由 404,核心问题往往不是路由本身写错了,而是环境切换后缓存未刷新、路由未重新编译,或环境配置未生效,致使请求匹配不到预期的路由规则。这类问题在从 dev 切到 prod 或反之、尤其是部署后手动改了 .env 或 app.php/app_dev.php 入口逻辑时高频出现。
确认当前生效的 APP_ENV 并清空对应缓存
环境变量切换后,Symfony 会为不同环境生成独立缓存(var/cache/dev/、var/cache/prod/)。若你改了 APP_ENV=prod,但没清 prod 缓存,旧的 dev 路由定义仍可能被加载,或容器根本没重建。
- 执行
php bin/console cache:clear --env=prod(确保命令中--env值与实际环境一致) - 检查
var/cache/下是否只存在目标环境目录(如只有prod/,没有残留的dev/) - 如果使用 APCu 或 Redis 做缓存,还需执行
php bin/console cache:pool:clear cache.global_clearer --env=prod
验证路由是否真被该环境加载
Symfony 2 的路由加载依赖 routing.yml 中的 resource 引用路径,而这些路径可受环境变量控制(例如通过 %kernel.environment% 动态拼接)。若配置里用了条件判断但写法有误,会导致某环境下路由文件根本没被 include。
- 运行
php bin/console debug:router --env=prod,看目标路由是否出现在列表中 - 检查
app/config/routing.yml或主路由文件,确认没有类似when: '%kernel.environment%' == 'dev'这类仅限某环境才加载的区块遗漏了你的路由 - 若路由定义在 bundle 内,确认该 bundle 在
AppKernel.php的registerBundles()方法中,对当前环境是启用的(例如没写成if ('prod' === $this->getEnvironment()) { ... }却漏掉了你的 bundle)
检查入口文件是否匹配目标环境
Symfony 2 默认有两个入口:web/app_dev.php(开发)和 web/app.php(生产)。它们各自设置了不同的环境常量和调试开关。如果 URL 指向的是 app.php,但你期望它走 dev 路由,就会 404——因为 app.php 强制 APP_DEBUG=false 且只加载 prod 配置。
- 确认你访问的 URL 对应哪个入口:比如
http://yoursite.com/app_dev.php/my-route才会走 dev 环境 - 若想让根路径
/直接走 prod,必须确保 Web 服务器 DocumentRoot 指向web/,且默认首页是app.php(Apache/Nginx 需配置DirectoryIndex app.php) - 临时测试:直接在浏览器访问
http://localhost/app.php/_profiler,若返回 404,说明app.php确实没加载 profiler 路由——这正表明它处于纯 prod 模式,不加载 dev-only 路由
留意 .env 文件与内联环境变量冲突
Symfony 2 虽不原生支持 .env(那是 Symfony 3.4+ 的特性),但如果你手动引入了 symfony/dotenv 或自定义加载逻辑,就可能出现变量覆盖混乱。例如 APP_ENV 在 app.php 中硬编码为 'prod',但 .env 里又设为 dev,最终以谁为准取决于加载顺序。
- 打开
web/app.php和web/app_dev.php,查看$env和$debug变量是否被显式赋值,优先级高于外部变量 - 搜索项目中是否有
putenv('APP_ENV=...')或$_SERVER['APP_ENV'] = ...类代码,它们会覆盖环境文件 - 最稳妥做法:删掉所有非标准的环境变量加载逻辑,严格靠入口文件控制环境



















