如何将代码从 PHP 7.4 迁移到 8.1

随着 PHP 7.4 近期终止生命周期,现在是迁移代码的时候了。这里有一些可供选择的方案。
2 位读者喜欢这篇文章。
arrows cycle symbol for failing faster

Opensource.com

PHP 7.4 的生命周期结束 (EOL) 日期是 2022 年 11 月 28 日星期一。如果你和我一样,这个日期比预期的来得更快。虽然你的 PHP 7.4 代码不会立即停止工作,但你确实需要开始为这个代码库的未来制定计划。

你有哪些选择?

你可以继续停留在 PHP 7.4,但更新有很多好处。最大的好处是安全风险和支持。随着我们离 EOL 日期越来越远,攻击者会将注意力转向 PHP 7.4,因为他们知道在大多数系统中,他们发现的任何漏洞都将无法得到修补。停留在 PHP 7.4 会大大增加你的网站未来被入侵的风险。同样,当你遇到 PHP 7.4 的问题时,寻求支持将变得越来越困难。此外,你很可能开始遇到与第三方代码/软件包的兼容性问题,因为它们会更新代码以兼容更高版本并放弃对 7.4 的支持。你还将错过 8.0 版本中引入的,并在 8.1 版本中进一步改进的 显著的速度和性能提升。但是升级所有这些遗留代码令人望而生畏!

从哪里开始?

幸运的是,PHP 提供了从 PHP 7.4 到 8.0 的 官方迁移指南,以帮助你入门(以及从 8.0 到 8.1 的迁移指南)。请务必通读“向后不兼容的更改”和“已弃用的功能”部分。虽然这些指南非常方便,但你可能需要检查成千上万行的代码,其中一些可能是你继承的。幸运的是,有一些选项可以帮助你找出迁移中潜在的问题区域。

PHPCodeSniffer + PHPCompatibility sniffs

PHPCodeSniffer (PCS) 是一个用于 PHP 代码语法检查的软件包。它根据一组定义的规则(也称为“sniffs”)检查你的代码,这些规则被称为“标准”。 PHPCodeSniffer 附带了一系列你可以使用的标准,包括 PEAR、PSR1、PSR2、PSR12、Squiz 和 Zend。幸运的是,你可以编写自己的 sniffs 集合来定义你喜欢的任何规则集。

PHPCompability 已加入对话

PHPCompatibility “是一组用于 PHP CodeSniffer 的 sniffs,用于检查 PHP 跨版本兼容性”,允许你测试代码库与不同 PHP 版本的兼容性,包括 PHP 8.0 和 8.1。这意味着你可以使用 PHPCodeSniffer 扫描你的代码库,应用 PHPCompability 中的规则来嗅探可能存在的任何与 PHP 8.1 不兼容的地方。

在我继续之前...

虽然 PHP8.2 已于 2022 年 12 月 8 日发布,并且我鼓励你开始查看 官方 8.1 到 8.2 迁移指南 并开始制定升级计划,但我在本文中提到的大多数检查器此时尚未完全支持 8.2。由于这些原因,我将专注于将代码迁移到 PHP8.1,而不是 8.2。

在撰写本文的过程中,我发现 PHPCompatiblity 在检查与 PHP 8.0/8.1 的兼容性时存在一个 已知问题,它会将本应是错误的问题报告为警告。 目前唯一的解决方法是使用 PHPCompatibility 的 develop 分支而不是 master。虽然他们声明它是稳定的,但请注意,在本文中,我使用的是非稳定分支。你可能需要在任何地方(而不仅仅是在本地开发环境中)实施 develop 分支之前权衡其利弊。虽然我发现 PCS+PHPCompatibility 是检查不兼容代码的最直接和全面的解决方案,但如果你不想使用非稳定版本的 PCS,请参阅本文末尾关于替代选项的部分。

为了本文的目的,我将使用 SimpleSAMLphp 的 1.4.6 版本 来测试不兼容性。这是一个六年前的代码库版本。我这样做不是为了挑剔 SimpleSAMLphp,而是因为我想要一些肯定会有错误的东西。事实证明,我测试的所有 platform.sh 代码以及我自己的代码都已经与 PHP8.1 兼容,并且不需要任何更改。

开始

要开始,首先克隆你的代码库,然后创建一个新分支。你现在需要决定是否要在本地机器上安装依赖项并运行扫描,还是在使用诸如 DDEVLandoDocksal 之类的本地开发环境中进行。在本演示中,我使用的是 DDEV。我建议使用本地开发环境而不是直接在本地机器上运行,因为虽然不强制要求使用你要测试的目标 PHP 版本,但为了获得最佳结果,建议你这样做。如果你没有安装 PHP,或者没有安装目标版本,本地开发环境允许你创建一个临时的环境,其中包含你需要的确切内容,而无需更改你的机器。

在为 PHP 8.1 设置好环境后,在终端提示符下(在我的例子中,我已经运行了 ddev start,一旦容器可用,使用 ddev ssh 进入 Web 应用程序),你需要添加这些新软件包,以便使用它们进行测试。我将使用 composer 添加它们,但是,如果你希望以不同的方式进行操作,则有 多种 方法安装 它们。如果你的代码库尚未使用 composer,则需要在继续之前执行 composer init

因为你将使用 PHPCompatibility 的 develop 分支,所以需要执行几个额外的步骤,这些步骤不在常规安装说明中。首先,PHPCompatibility 的 develop 分支需要 alpha 版本的 phpcsstandards/phpcsutils。因为它被标记为 alpha 版本,所以你需要让 composer 知道即使此软件包低于你的最低稳定性要求,也可以安装。

$ composer require --dev phpcsstandards/phpcsutils:"^1.0@dev"

接下来,安装以 develop 分支为目标的 PHPCompatibility

$ composer require --dev phpcompatibility/php-compatibility:dev-develop

develop 分支还安装了 dealerdirect/phpcodesniffer-composer-installer,因此你无需手动添加它或将 PCS 指向此新标准。

要验证我们的新标准是否已安装,你需要让 PCS 显示它知道的标准。

$ phpcs -i
The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, PHPCompatibility, PHPCS23Utils and PHPCSUtils

现在你知道你的标准可用了,你可以让 PCS 扫描我们的代码。要指示 PCS 使用特定标准,请使用 --standard 选项并告诉它使用 PHPCompatibility。但是,你还需要告诉 PHPCompatibility 你要针对哪个 PHP 版本进行测试。为此,请使用 PCS 的 --runtime-set 选项,并将键 testVersion 和值 8.1 传递给它。

在开始扫描之前,剩下的一个问题是你要扫描的代码位于项目根目录 (.) 中,但 vendor 目录也位于项目根目录中。你不希望扫描 vendor 中的代码,因为这些不是你必须控制的软件包。PCS 允许你使用 --ignore 选项告诉它不要扫描文件/目录。最后,你希望在 PCS 解析文件时看到进度,因此你将传入 -p 选项。

将它们放在一起

$ phpcs -p . --standard=PHPCompatibility --runtime-set testVersion 8.1 --ignore=*/vendor/*

这将启动 PCS,它将在扫描你的项目代码时输出其进度。W 表示警告E 表示错误。扫描结束时,它将输出:一份完整报告,其中包含包含问题的文件、问题发生的行号、问题是警告还是错误,以及发现的具体问题。

一般来说,错误是指将在 PHP 8.1 中导致致命错误的事情,需要在迁移之前修复。警告可能是指在 8.0/8.1 中已弃用但尚未删除的内容,或者 PCS 在尝试解析文件时遇到的问题。

asciicast

鉴于报告可能很长,并且一次性输出到你的终端,因此有 多种选项 可用于更改报告中包含的信息,以及多种报告格式。

当你开始修复代码时,你可以根据需要多次重新运行报告。但是,在某些时候,你需要使用真实数据在实际的 PHP8.1 环境中测试代码。如果你使用的是 Platform.sh,这非常容易,只需创建一个分支,更改配置文件中的一行,然后将该分支推送到我们即可。你可以查看 此视频,了解它有多么容易!

有太多需要修复的东西了!

既然你已经对迁移之前需要更新的内容有了清晰的了解,你可能会面临大量的工作要做。幸运的是,你有一些选项可以帮助你。PCS 附带了一个名为 PHP Code Beautifier and Fixer (phpcbf) 的代码修复器。运行 phpcbf 几乎与运行 phpcs 相同,并且大多数选项都是相同的。另一个选项是 Rector。这些工具的用法超出了本文的范围,但与任何自动化一样,你需要在将更改提升到生产环境之前进行测试和验证。

替代选项

如果出于任何原因,你觉得使用非稳定版本的 PCS 不舒服,那么你还有其他选项可以检查你的代码。

Phan

Phan 是一个用于 PHP 的静态代码分析器。它提供多个级别的分析,并允许逐步加强该分析。

“如果你想避免你的团队失去理智,则需要缓慢地引入静态分析。”

Phan 不仅针对与较新版本的兼容性,它还可以突出显示在更高版本中会出错的代码区域。但是,在使用 Phan 检查兼容性时,存在一些注意事项

  • 比 PCS+PHPCompatibility 慢。
  • Phan 需要 ast php 扩展,该扩展在 Platform.sh(或 DDEV)上默认不可用。你需要在本地开发环境中安装它并将其添加到你的 php.ini 文件中。或者,你可以使用 --allow-polyfill-parser 选项,但这会慢得多。
  • Phan 的默认报告输出不如其他选项易于阅读
  • 我遇到了一个问题,如果你的代码库通过 composer 的 [config:vendor-dir](https://getcomposer.org.cn/doc/06-config.md#vendor-dir) 选项设置了不同的 vendor 目录,它会报错,指出它无法在 vendor 目录中找到某些文件
  • 如前所述,Phan 分析的内容远不止 PHP8.1 兼容性。虽然在其他情况下这肯定是一个优势,但如果你的目标是尽快从 7.4 迁移到 8.1,你将不得不解析与版本兼容性无关的错误。
  • 要求你在要定位的 PHP 版本上运行它

PHPStan

与 Phan 类似,PHPStan 是一个用于 PHP 的静态代码分析器,它承诺“无需编写测试即可发现错误”。并且适用类似的注意事项

  • 比 PCS 或 Phan 慢
  • 分析的内容远不止 PHP8.1 兼容性,因此根据你当前的代码库,你可能必须解析大量与版本兼容性无关的错误
  • 要求你在要定位的 PHP 版本上运行它

PHP Parallel Lint

一个非常快速的 PHP linter,可以 lint 你的代码库以查找问题,但也可以检查弃用。虽然它非常快,但它只是一个 linter,因此只能显示在编译时而不是运行时抛出的弃用。在我的示例代码中,它仅发现了 2 个弃用,而 PCS 发现了 960 个弃用。

总结

代码迁移虽然从来都不有趣,但对于最大限度地降低组织风险至关重要。Platform.sh 使你可以灵活地使用与生产站点相同的数据和配置来测试你的代码,但在隔离的环境中进行测试。将此与上述工具结合使用,你将拥有强大而高效的代码迁移所需的一切。


本文最初发布在 Platform.sh 社区站点,并已获得许可重新发布。

Paul Gilzow wearing sunglasses and smiling
Platform.sh 的开发者关系工程师。密苏里大学前程序员/分析师主管。Web 应用程序安全和可访问性布道者。软件讲师。会议讲师和演示者。靠激情和咖啡运转。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可获得许可。
© . All rights reserved.