必须分步升级:4.4→5.4→6.4→7.4,每步验证容器、路由及弃用警告;PHP≥8.4,ext-intl(ICU≥72.1)、ext-redis(≥6.1)、ext-mbstring须启用;重点改造路由属性化、表单by_reference、事件契约接口及模板路径迁移。

直接从旧版(比如 4.4 或更早)升到 Symfony 7.4 不现实,会卡在 FlattenException 找不到、TranslatorInterface::trans() 参数不匹配、路由匹配失败等地方。必须分步走,每步验证,否则越往后越难回退。
先确认 PHP 和扩展是否达标
Symfony 7.4 要求 PHP ≥ 8.4,且 ext-intl、ext-redis(≥6.1)、ext-mbstring 必须启用。别只看 php -v,要实测:
-
php -m | grep -E "(intl|redis|mbstring)"确认模块已加载 -
php -r "echo INTL_ICU_VERSION;"检查 ICU 版本是否 ≥ 72.1(7.4 强依赖) - 若用 Redis 缓存,
composer show phpredis/phpredis确保 ≥6.1;用 Relay 的话,relay.so版本得 ≥0.11
按路径逐级升级:4.4 → 5.4 → 6.4 → 7.4
跳版本等于主动引入未知断裂点。每个中间版本升级后,必须运行三件事:
-
bin/console debug:container --types看服务是否全注册成功 -
bin/console debug:router检查路由是否还能匹配,尤其注意{lang}这类占位符是否漏了->requirements() - 打开 Profiler 的 “Deprecations” 标签页,刷几个页面,把所有
[DEPRECATED]警告清零再进下一步
升级命令统一用:composer require symfony/symfony:^X.Y --update-with-dependencies(X.Y 替换为当前目标版本),别用 update 全局拉,容易带偏其他包。
重点改这四类高频断裂点
这些在 5.4→6.4→7.4 过程中反复出现,几乎必改:
- 路由:所有
@Route注解必须转成 PHP 属性#[Route],YAML/PHP 路由里_locale默认值、正则约束(->requirements(['lang' => '[a-z]{2}']))不能省 - 表单:新实体绑定时若没
flush,ID 可能为空,需加'by_reference' => false或改用 DTO - 事件:
Symfony\Component\EventDispatcher\Event已移除,全部换Symfony\Contracts\EventDispatcher\Event,并确保装了symfony/contracts - 模板:所有
src/Bundle/Resources/views/下的模板必须挪到templates/,路径引用同步更新
Debug 和 Translation 组件要单独处理
symfony/debug 在 4.4 就废弃、5.0 彻底删除,FlattenException 不是路径错了,是类真移到 symfony/error-handler 里了:
- 执行
composer remove symfony/debug && composer require symfony/error-handler - 把所有
use Symfony\Component\Debug\Exception\FlattenException;改成use Symfony\Component\ErrorHandler\Exception\FlattenException; - 检查你自定义的异常格式化逻辑 —— 新
FlattenException的getTrace()返回结构略有不同,getAllPrevious()行为也变了 - Translation 升级到 7.3 后,
trans()方法第四个参数$locale变成非可选(虽可传null),老实现类必须补上,否则 PHP 直接报Declaration must be compatible
真正麻烦的不是改代码,而是那些没被 Profiler 捕获的隐式调用 —— 比如自定义日志处理器里悄悄用了旧 FlattenException 构造方式,或 Twig 扩展里硬编码了模板路径。这类问题往往上线后才暴露,得靠搜索整个 src/ 和 templates/ 目录,别只盯报错堆栈。


















