升级第三方 Bundle 以适配 Symfony 主要版本
Symfony 3 于 2015 年 11 月发布。虽然此版本不包含任何新功能,但它移除了之前 2.8 版本中包含的所有向后兼容层。如果您的 Bundle 使用了任何已弃用的功能,并作为第三方 Bundle 发布,则升级到 Symfony 3 的应用程序将无法再使用它。
允许安装 Symfony 3 组件
大多数第三方 Bundle 在 composer.json
文件中使用 ~2.N
或 ^2.N
约束来定义其 Symfony 依赖项。例如
1 2 3 4 5 6 7
{
"require": {
"symfony/framework-bundle": "~2.7",
"symfony/finder": "~2.7",
"symfony/validator": "~2.7"
}
}
这些约束阻止 Bundle 使用 Symfony 3 组件,这意味着 Bundle 无法安装在基于 Symfony 3 的应用程序中。 感谢 Composer 依赖约束的灵活性,您可以通过将 ~2.N
替换为 ~2.N|~3.0
(或将 ^2.N
替换为 ^2.N|~3.0
) 来指定多个主要版本。
上面的示例可以更新为与 Symfony 3 一起使用,如下所示
1 2 3 4 5 6 7
{
"require": {
"symfony/framework-bundle": "~2.7|~3.0",
"symfony/finder": "~2.7|~3.0",
"symfony/validator": "~2.7|~3.0"
}
}
提示
在第三方 Bundle 上发现的另一个常见版本约束是 >=2.N
。您应该避免使用该约束,因为它太通用(这意味着您的 Bundle 与任何未来的 Symfony 版本兼容)。请改为使用 ~2.N|~3.0
或 ^2.N|~3.0
,以使您的 Bundle 在未来也能兼容。
查找并修复弃用
除了允许用户将您的 Bundle 与 Symfony 3 一起使用之外,您的 Bundle 还必须停止使用 2.8 版本已弃用的任何功能,因为这些功能在 3.0 中已移除(您将收到异常或 PHP 错误)。检测弃用最简单的方法是安装 symfony/phpunit-bridge package 包,然后运行测试套件。
首先,将该组件作为 Bundle 的 dev
依赖项安装
1
$ composer require --dev symfony/phpunit-bridge
然后,运行您的测试套件,并查找在 PHPUnit 测试报告后显示的弃用列表
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
# ... PHPUnit output
Remaining deprecation notices (3)
The "pattern" option in file ... is deprecated since version 2.2 and will be
removed in 3.0. Use the "path" option in the route definition instead ...
Twig Function "form_enctype" is deprecated. Use "form_start" instead in ...
The Symfony\Bundle\SecurityBundle\SecurityContext class is deprecated since
version 2.6 and will be removed in 3.0. Use ...
修复报告的弃用,再次运行测试套件,并重复该过程,直到没有报告弃用用法。
实用资源
有几个资源可以帮助您检测、理解和修复已弃用功能的使用
- Symfony 官方 2.x 到 3.0 升级指南
- 升级到 Symfony 3.0 所需的完整更改列表,并按组件分组。
- SensioLabs DeprecationDetector
- 它对您项目的源代码运行静态代码分析,以查找已弃用方法、类和接口的用法。 它适用于任何 PHP 应用程序,但它包含 Symfony 应用程序的特殊检测器,在 Symfony 应用程序中,它还可以检测已弃用服务的使用。
- Symfony Upgrade Fixer
- 它分析 Symfony 项目以查找弃用。此外,由于支持的“修复器”列表不断增加,它还可以自动解决其中一些问题。
在 Symfony 3 中测试您的 Bundle
既然您的 Bundle 已移除所有弃用,现在是在 Symfony 3 应用程序中进行真实测试的时候了。假设您已经有一个 Symfony 3 应用程序,您可以在本地测试更新后的 Bundle,而无需通过 Composer 安装它。
如果您的操作系统支持符号链接,请将相应的 vendor 目录指向您的本地 Bundle 根目录
1
$ ln -s /path/to/your/local/bundle/ vendor/you-vendor-name/your-bundle-name
如果您的操作系统不支持符号链接,您需要将您的本地 Bundle 目录复制到 vendor/
内的相应目录中。
更新 Travis CI 配置
除了在本地运行工具之外,建议设置 Travis CI 服务,以使用不同的 Symfony 配置运行您的 Bundle 测试。使用以下推荐配置作为您自己配置的起点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
language: php
php:
- 5.3
- 5.6
- 7.0
matrix:
include:
- php: 5.3.3
env: COMPOSER_FLAGS='--prefer-lowest --prefer-stable' SYMFONY_DEPRECATIONS_HELPER=max[total]=999999
- php: 5.6
env: SYMFONY_VERSION='2.7.*'
- php: 5.6
env: SYMFONY_VERSION='2.8.*'
- php: 5.6
env: SYMFONY_VERSION='3.0.*'
- php: 5.6
env: SYMFONY_VERSION='3.1.*'
- php: 5.6
env: DEPENDENCIES='dev' SYMFONY_VERSION='3.2.*@dev'
before_install:
- composer self-update
- if [ "$DEPENDENCIES" == "dev" ]; then perl -pi -e 's/^}$/,"minimum-stability":"dev"}/' composer.json; fi;
- if [ "$SYMFONY_VERSION" != "" ]; then composer --no-update require symfony/symfony:${SYMFONY_VERSION}; fi;
install: composer update $COMPOSER_FLAGS
script: phpunit
同时更新代码以支持 Symfony 2.x 和 3.x
为您的 Bundle 添加 Symfony 3 支持的真正挑战是,当您想使用相同的代码同时支持 Symfony 2.x 和 3.x 时。在某些极端情况下,您需要处理 API 差异。
在深入研究最常见极端情况的具体细节之前,一般的建议是**不要依赖 Symfony Kernel 版本**来决定要使用哪个代码
1 2 3 4 5
if (Kernel::VERSION_ID < 20800) {
// code for Symfony 2.x
} else {
// code for Symfony 3.x
}
不要检查 Symfony Kernel 版本,而是检查特定组件的版本。 例如,OptionsResolver API 在其 2.6 版本中通过添加 setDefined()
方法进行了更改。 在这种情况下,推荐的检查方法是
1 2 3 4 5 6 7
use Symfony\Component\OptionsResolver\OptionsResolver;
if (!method_exists(OptionsResolver::class, 'setDefined')) {
// code for the old OptionsResolver API
} else {
// code for the new OptionsResolver API
}
提示
在一种情况下,您实际上可以依赖 Symfony\Component\HttpKernel\Kernel::VERSION_ID
常量:当尝试检测 symfony/http-kernel
组件的版本时,因为它是定义此常量的组件。