升级主要版本(例如 6.4.0 到 7.0.0)
每两年,Symfony 都会发布一个新的主要版本(第一个数字会更改)。这些版本是最难升级的,因为它们允许破坏向后兼容性。但是,Symfony 使这个升级过程尽可能顺利。
这意味着您可以在主要版本实际发布之前更新大部分代码。这被称为使您的代码未来兼容。
升级主要版本有几个步骤:
1) 使您的代码不出现弃用
在一个主要版本的生命周期中,会添加新功能,并且方法签名和公共 API 用法会更改。但是,次要版本不应包含任何向后不兼容的更改。为了实现这一点,“旧的”(例如函数、类等)代码仍然有效,但被标记为已弃用,表明它将在未来被删除/更改,您应该停止使用它。
当主要版本发布时(例如 7.0.0),所有已弃用的特性和功能都将被删除。因此,只要您更新了代码以停止在主要版本之前的最后一个版本(例如 6.4.*
)中使用这些已弃用的特性,您应该能够顺利升级。这意味着您应该首先升级到最新的次要版本(例如 5.4),以便您可以看到所有的弃用。
为了帮助您找到弃用,当您最终使用已弃用的特性时,会触发通知。当在浏览器中访问 开发环境中的应用程序时,这些通知会显示在 Web 开发工具栏中。

最终,您的目标应该是停止使用已弃用的功能。有时,警告可能会准确地告诉您需要更改什么。
但有时,警告可能不清楚:某个地方的设置可能会导致更深层的类触发警告。在这种情况下,Symfony 会尽力给出清晰的消息,但您可能需要进一步研究该警告。
有时,警告可能来自您正在使用的第三方库或扩展包。如果是这样,很有可能这些弃用已经被更新了。在这种情况下,升级库以修复它们。
提示
Rector 是一个第三方项目,可以自动升级和重构 PHP 项目。Rector 包含一些规则来自动修复某些 Symfony 弃用。
一旦所有弃用警告都消失了,您就可以更有信心地升级。
PHPUnit 中的弃用
当您使用 PHPUnit 运行测试时,不会显示弃用通知。为了帮助您,Symfony 提供了一个 PHPUnit bridge。这个 bridge 将在测试报告的末尾向您显示所有弃用通知的精美摘要。
您只需要安装 PHPUnit bridge:
1
$ composer require --dev symfony/phpunit-bridge
现在,您可以开始修复通知:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# this command is available after running "composer require --dev symfony/phpunit-bridge"
$ ./bin/phpunit
...
OK (10 tests, 20 assertions)
Remaining deprecation notices (6)
The "request" service is deprecated and will be removed in 3.0. Add a type-hint for
Symfony\Component\HttpFoundation\Request to your controller parameters to retrieve the
request instead: 6x
3x in PageAdminTest::testPageShow from Symfony\Cmf\SimpleCmsBundle\Tests\WebTest\Admin
2x in PageAdminTest::testPageList from Symfony\Cmf\SimpleCmsBundle\Tests\WebTest\Admin
1x in PageAdminTest::testPageEdit from Symfony\Cmf\SimpleCmsBundle\Tests\WebTest\Admin
一旦您修复了所有这些,命令将以 0
(成功)结束,您就完成了!
警告
您可能会看到许多关于不兼容的原生返回类型的弃用。请参阅 添加原生返回类型,以获得修复这些弃用的指导。
2) 通过 Composer 更新到新的主要版本
一旦您的代码不出现弃用,您可以通过 Composer 更新 Symfony 库,方法是修改您的 composer.json
文件,并将所有以 symfony/
开头的库更改为新的主要版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
{
"...": "...",
"require": {
- "symfony/config": "6.4.*",
+ "symfony/config": "7.0.*",
- "symfony/console": "6.4.*",
+ "symfony/console": "7.0.*",
"...": "...",
"...": "A few libraries starting with symfony/ follow their own
versioning scheme (e.g. symfony/polyfill-[...],
symfony/ux-[...], symfony/[...]-bundle).
You do not need to update these versions: you can
upgrade them independently whenever you want",
"symfony/monolog-bundle": "^3.10",
},
"...": "...",
}
处理 Symfony 依赖项更新的更有效方法是在您的 composer.json
文件中设置 extra.symfony.require
配置选项。在使用 Symfony Flex 的 Symfony 应用程序中,此设置将 Symfony 包限制为单个特定版本,从而提高依赖项管理和 Composer 更新性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
{
"...": "...",
"require": {
- "symfony/cache": "7.0.*",
+ "symfony/cache": "*",
- "symfony/config": "7.0.*",
+ "symfony/config": "*",
- "symfony/console": "7.0.*",
+ "symfony/console": "*",
"...": "...",
},
"...": "...",
+ "extra": {
+ "symfony": {
+ "require": "7.0.*"
+ }
+ }
}
警告
像 dependabot 这样的工具可能会忽略此设置并升级 Symfony 依赖项。有关更多详细信息,请参阅关于 dependabot 的这个 GitHub 问题。
提示
如果提供了更新的次要版本(例如 6.4
),您可以直接使用该版本并跳过旧版本(6.0
、6.1
等)。查看维护的 Symfony 版本。
接下来,使用 Composer 下载库的新版本:
1
$ composer update "symfony/*"
更新到新的主要版本后的最佳实践是清除缓存。与其运行 cache:clear
命令(如果在升级后应用程序在控制台中不可引导,则该命令将不起作用),不如删除整个缓存目录的内容:
1 2 3 4 5
# run this command on Linux and macOS
$ rm -rf var/cache/*
# run this command on Windows
C:\> rmdir /s /q var\cache\*
依赖错误
如果您遇到依赖错误,则可能意味着您还需要升级作为 Symfony 库依赖项的其他库。要允许这样做,请传递 --with-all-dependencies
标志:
1
$ composer update "symfony/*" --with-all-dependencies
这将更新 symfony/*
和这些包依赖的所有包。通过在 composer.json
中使用严格的版本约束,您可以控制每个库升级到的版本。
如果这仍然不起作用,则您的 composer.json
文件可能为与较新 Symfony 版本不兼容的库指定了版本。在这种情况下,在 composer.json
中将该库更新到较新版本可能会解决问题。
或者,您可能遇到更深层次的问题,即不同的库依赖于其他库的冲突版本。检查您的错误消息以进行调试。
可能发生的另一个问题是,项目依赖项可以安装在您的本地计算机上,但不能安装在远程服务器上。当每台机器上的 PHP 版本不同时,通常会发生这种情况。解决方案是将 platform 配置选项添加到您的 `composer.json` 文件中,以定义依赖项允许的最高 PHP 版本(将其设置为服务器的 PHP 版本)。
3) 更新 Recipes
随着时间的推移,尤其是当您升级到库的新版本时,recipe 的更新版本可能会可用。这些更新通常是次要的,例如配置文件中的新注释,但最好使您的文件与 recipe 保持同步。
Symfony Flex 提供了几个命令来帮助升级您的 recipes。在开始之前,请务必提交您正在处理的任何不相关的更改:
1.18
recipes:update
命令是在 Symfony Flex 1.18 中引入的。
1 2 3 4 5 6 7 8 9 10 11
# choose an outdated recipe to update
$ composer recipes:update
# update a specific recipe
$ composer recipes:update symfony/framework-bundle
# see a list of all installed recipes and which have updates available
$ composer recipes
# see detailed information about a specific recipes
$ composer recipes symfony/framework-bundle
recipes:update
命令很智能:它会查看您安装 recipe 时和最新版本之间的差异。然后,它会创建一个补丁并将其应用于您的应用程序。如果存在任何冲突,您可以像正常的 git
冲突一样解决它们,并像正常情况一样提交。
4) 更新您的代码以使用新版本
在某些罕见的情况下,下一个主要版本可能包含向后兼容性中断。请务必阅读 Symfony 仓库中包含的 UPGRADE-X.0.md
(其中 X 是新的主要版本),以了解您需要注意的任何 BC 破坏。
升级到 Symfony 6:添加原生返回类型
Symfony 6 和 Symfony 7 为(几乎所有)方法添加了原生 PHP 返回类型。
在 PHP 中,如果父类具有返回类型声明,则任何实现或覆盖该方法的类也必须具有返回类型。但是,您可以在父类添加返回类型之前添加返回类型。这意味着在升级到 Symfony 6.0 或 7.0 之前,将原生 PHP 返回类型添加到您的类非常重要。否则,您将收到不兼容的声明错误。
当调试模式启用时(通常在开发和测试环境中),Symfony 将为每个不兼容的方法声明触发弃用。例如,UserInterface::getRoles()
方法在 Symfony 6 中将具有 array
返回类型。在 Symfony 5.4 中,您将收到关于此的弃用通知,您必须将返回类型声明添加到您的 getRoles()
方法中。
为了帮助解决这个问题,Symfony 提供了一个脚本,可以为您自动添加这些返回类型。确保您已安装 symfony/error-handler
组件。安装后,使用 Composer 生成完整的类映射,并运行脚本以迭代类映射并修复任何不兼容的方法:
1 2 3 4 5 6 7
# Make sure "exclude-from-classmap" is not filled in your "composer.json". Then dump the autoloader:
# "-o" is important! This forces Composer to find all classes
$ composer dump-autoload -o
# patch all incompatible method declarations
$ ./vendor/bin/patch-type-declarations
提示
此功能不限于 Symfony 包。它还将帮助您添加类型并为项目中的其他依赖项做好准备。
可以使用 SYMFONY_PATCH_TYPE_DECLARATIONS
环境变量修改此脚本的行为。此环境变量的值是 url 编码的(例如 param1=value1¶m2=value2
),以下参数可用:
force
-
启用修复返回类型,该值必须是以下之一:
2
添加所有可能的返回类型(默认,推荐用于应用程序);1
仅向测试、final、internal 或 private 方法添加返回类型;phpdoc
仅向不兼容的方法添加@return
docblock 注释,或者如果由 PHP 引擎触发,则添加#[\ReturnTypeWillChange]
。
php
- PHP 的目标版本 - 例如
7.1
不会生成 "object" 类型(在 7.2 中引入)。默认设置为运行脚本时使用的 PHP 版本。 deprecations
- 设置为
0
以禁用弃用。否则,当子类缺少返回类型,而父类声明了@return
注释时,将发出弃用通知(默认为1
)。
如果存在应忽略的特定文件,您可以将 SYMFONY_PATCH_TYPE_EXCLUDE
环境变量设置为正则表达式。此正则表达式将与类的完整路径匹配,并且每个匹配的路径都将被忽略(例如 SYMFONY_PATCH_TYPE_EXCLUDE="/tests\/Fixtures\//"
)。vendor/
目录中的类始终被忽略。
提示
该脚本不关心代码风格。在修补类型后,运行您的代码风格修复器,或使用 phpdoc_trim_consecutive_blank_line_separation
、no_superfluous_phpdoc_tags
和 ordered_imports
规则的 PHP CS Fixer。