跳到内容

升级主要版本(例如 6.4.0 到 7.0.0)

编辑此页

每两年,Symfony 都会发布一个新的主要版本(第一个数字会更改)。这些版本是最难升级的,因为它们允许破坏向后兼容性。但是,Symfony 使这个升级过程尽可能顺利。

这意味着您可以在主要版本实际发布之前更新大部分代码。这被称为使您的代码未来兼容

升级主要版本有几个步骤:

  1. 使您的代码不出现弃用;
  2. 通过 Composer 更新到新的主要版本;
  3. 更新您的代码以使用新版本.

1) 使您的代码不出现弃用

在一个主要版本的生命周期中,会添加新功能,并且方法签名和公共 API 用法会更改。但是,次要版本不应包含任何向后不兼容的更改。为了实现这一点,“旧的”(例如函数、类等)代码仍然有效,但被标记为已弃用,表明它将在未来被删除/更改,您应该停止使用它。

当主要版本发布时(例如 7.0.0),所有已弃用的特性和功能都将被删除。因此,只要您更新了代码以停止在主要版本之前的最后一个版本(例如 6.4.*)中使用这些已弃用的特性,您应该能够顺利升级。这意味着您应该首先升级到最新的次要版本(例如 5.4),以便您可以看到所有的弃用。

为了帮助您找到弃用,当您最终使用已弃用的特性时,会触发通知。当在浏览器中访问 开发环境中的应用程序时,这些通知会显示在 Web 开发工具栏中。

The Logs page of the Symfony Profiler showing the deprecation notices.

最终,您的目标应该是停止使用已弃用的功能。有时,警告可能会准确地告诉您需要更改什么。

但有时,警告可能不清楚:某个地方的设置可能会导致更深层的类触发警告。在这种情况下,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(成功)结束,您就完成了!

警告

您可能会看到许多关于不兼容的原生返回类型的弃用。请参阅 添加原生返回类型,以获得修复这些弃用的指导。

有时,您无法修复所有弃用(例如,某些东西在 6.4 中被弃用,而您仍然需要支持 6.3)。在这些情况下,您仍然可以使用 bridge 来修复尽可能多的弃用,然后允许更多弃用以使您的测试再次通过。您可以通过使用 SYMFONY_DEPRECATIONS_HELPER 环境变量来做到这一点:

1
2
3
4
5
6
7
8
<!-- phpunit.xml.dist -->
<phpunit>
    <!-- ... -->

    <php>
        <env name="SYMFONY_DEPRECATIONS_HELPER" value="max[total]=999999"/>
    </php>
</phpunit>

您也可以像这样执行命令:

1
$ SYMFONY_DEPRECATIONS_HELPER=max[total]=999999 php ./bin/phpunit

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.06.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 版本)。

升级其他包

您可能还想升级其余的库。如果您在 composer.json 中的版本约束方面做得很好,那么您可以通过运行以下命令安全地执行此操作:

1
$ composer update

警告

请注意,如果您在 composer.json 中有一些不明确的版本约束(例如 dev-master),这可能会将一些非 Symfony 库升级到包含向后兼容性破坏性更改的新版本。

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&param2=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_separationno_superfluous_phpdoc_tagsordered_imports 规则的 PHP CS Fixer

开源扩展包和软件包在添加返回类型时需要更加谨慎,因为添加返回类型会强制所有扩展该类的用户也添加返回类型。推荐的方法是使用 2 步过程:

  1. 首先,创建一个次要版本(即没有向后兼容性中断的版本),您可以在其中添加可以安全引入的类型,并为所有其他方法添加 @return PHPDoc:

    1
    2
    3
    4
    5
    6
    # Add type declarations to all internal, final, tests and private methods.
    # Update the "php" parameter to match your minimum required PHP version
    $ SYMFONY_PATCH_TYPE_DECLARATIONS="force=1&php=7.4" ./vendor/bin/patch-type-declarations
    
    # Add PHPDoc to the leftover public and protected methods
    $ SYMFONY_PATCH_TYPE_DECLARATIONS="force=phpdoc&php=7.4" ./vendor/bin/patch-type-declarations

    运行脚本后,检查您的类并在缺少 @return PHPDoc 的地方添加更多。弃用和修补脚本完全基于 PHPDoc 信息工作。此版本的用户将收到弃用通知,告知他们将您软件包中缺少的返回类型添加到他们的代码中。

    如果您不需要任何 PHPDoc 并且您的所有方法声明已经与 Symfony 兼容,则可以安全地允许 Symfony 依赖项使用 ^6.0。否则,您必须继续执行 (2)。

  2. 创建一个新的主要版本(即带有向后兼容性中断的版本),您可以在其中为所有方法添加类型:

    1
    2
    # Update the "php" parameter to match your minimum required PHP version
    $ SYMFONY_PATCH_TYPE_DECLARATIONS="force=2&php=7.4" ./vendor/bin/patch-type-declarations

    现在,您可以安全地允许 Symfony 依赖项使用 ^6.0

这项工作,包括代码示例,均在 Creative Commons BY-SA 3.0 许可下获得许可。
目录
    版本