hostease美国服务器商将向您展示一些您可以部署的策略,以使现有代码库与 PHP 8 兼容。
静态分析工具,例如 PHPCompatibility 来检测语法问题。
自动测试以检测运行时问题。
手动测试以检测运行时问题。
根据您的测试套件的覆盖范围以及语法更改和运行时的比例,这些策略很好地用于修复代码库与新版本 PHP(目前正在讨论 PHP 8)的兼容性。确实,在 PHP 8 和 WordPress 的情况下,还有一些额外的挑战使得很难依赖这些策略来确保 WordPress 与 PHP 8 的完美兼容性。下面我们将报告我们已经部署的策略对于 WordPress 并分享结果。推荐阅读:《 如何将PHP更新为WordPress建议的版本 》
静态分析工具
由于 PHP 8.0 中的一些更改的性质,使用静态分析可以检测到的问题是有限的。在那些情况下,静态分析看起来超越了它们的传统潜力并计划跟踪变量和常量的值以及运行时类型,这种扫描的结果肯定会容易出现误报。静态分析工具除此之外,PHP Compatibility 是唯一一款用于查找 PHP 跨版本兼容性相关问题的静态分析工具。除了 PHP 兼容性之外,其他静态分析工具还报告了更大范围的问题。珍惜结果以检测与 PHP 跨版本兼容性相关且实际上正确的问题非常耗时,并且需要深入的工具相关知识,尤其是关于将它们配置为最小噪音的知识。同时,这些工具一直处于不稳定状态,试图继续 PHP 版本的变化并更新可能的扫描。因此,我们可以期待这些工具在未来检测到更多问题。因此,与目前已经存在并且可以进一步发现的东西无关,这些工具很有可能在(不远的)将来仍然会发现更多问题。
使用 PHPCompatibility 扫描 WordPress
“__destruct() 将不再在 __construct() 中的 die() 之后被调用”是 PHPCompatibility 发现的另一个 PHP 8 问题。扫描仪可以完美地检测到这一点。但是,经过进一步分析,发现在这种情况下没有问题。除此之外,PHPCompatibility 在“插件/主题编辑器”使用的代码中检测到问题。涉及代码的分析已确定代码中存在潜在的疏忽。在编辑器中,WordPress 期待对代码做最少的分析;但是,它没有考虑 PHP 5.3+ 代码。在考虑到 PHP8 中的相关变化的同时,这种疏忽现在变得更加复杂,难以解决。我们使用 PHPCompatibility 对开发版本进行了扫描,正如我们预期的那样,结果与我们使用之前的 PHP 更新获得的结果大不相同。扫描仪检测到的问题由外部维护。
使用 Exakat 扫描 WordPress
谈到 10 月 16 日发生的最新公开扫描,基于 WP 主干, Exakat 总共报告了 149.567 个问题。PHP 8 兼容性报告向我们展示了总共 93 个问题。但是,它是不完整的,因为与 PHP 8 相关的分析编号未包含在报告中。虽然我们预计这些报告会包含大量误报,因为 WordPress 不使用类型声明,因此类型是从找到的代码和 docblocks 中显示的类型推断出来的,但仍应单独检查这些问题。无论发现的问题中只有 1% 是正确的,但仍然会下降到大约 450 个错误,这仍然需要处理。除此之外,从误报中剔除真实问题需要大量时间。
使用 PHPStan 扫描 WordPress
使用PHPStan进行扫描需要完全定制的规则集才能获得远程可用的结果,但事实证明它们充满了一些误报,导致输出无法使用。注意:我们并不是在批评 PHPStan 工具,但这很大程度上是因为 WordPress 几乎不使用类型声明,而另一方面,PHPStan 主要倾向于使用现代代码的项目,不是吗?包含最基本配置的初始扫描将产生 20.000 多个问题。使用上述高度定制的规则集进行扫描,专门针对 PHP 8 相关问题,仍然会在级别 5 产生 580 个问题,在级别 7 产生额外的 2.150 个潜在问题。这些可能包含一些误报,但会产生更多 380 个问题在第 8 级有类似的警告。最近打开了一个Trac 票证,以解决基于未知配置的一系列问题,但完全针对您传递的参数类型不匹配(级别 5)。PR 草案可用于解决这些问题。对该 PR 的初步评估表明,大多数提议的修复都会将变量类型转换为预期的类型并隐藏问题,而不是通过正确检查来实际修复它们。如果这些更改没有伴随严格的单元测试,这会导致应用程序出现意外行为。除此之外,tit 可能会导致难度增加,同时肯定会进一步调试错误。目前,尚不确定建议的修复是否有必要,或者是否应将已识别的问题视为误报。推荐阅读:《如何给WordPress添加验证码以减少垃圾邮件》
测试
由于 PHP8 中存在问题的交换的性质,静态分析可以走这么远。手动审查和测试软件被证明是一项艰苦的工作,当有很多事情需要注意时,人类也很容易忽视一些事情。现在,谈到最终用户执行的测试,它们被证明是相对无用的,因为这通常会导致测试“快乐路径”。如果我们想获得更可靠的结果,那么我们需要全面的探索性和回归测试。测试拥有高质量的自动化测试并在 PHP 8 上运行这些测试比什么都重要。这将完美地表明预期的 PHP 8.0 问题。大多数技术极客都对 PHP 8.0 感到兴奋,当然,这次的变化是巨大的。每个人都将花费一些时间来了解 PHP 8 的兼容性、配置、优势等,其中弹出的最大问题之一是——“WordPress 是否已经与 PHP 8 兼容,如果不兼容,那么需要采取哪些措施是需要的。”好吧,一旦 PHP 8 发布,我们的专家时间就投入到最深层次的测试中,结果可能会让任何人感到震惊!是的,我们现在什么都知道了,并且很高兴炫耀我们的报告和测试结果。现在让我们继续在 PHP 8 上运行自动化测试。
在 PHP 8 上运行自动化测试
PHPUnit 9.3 是第一个与 PHP 8.0 正式兼容的 PHPUnit 版本,于 2020 年 8 月发布。好吧,在 PHP 上运行自动化测试套件很困难,因为事实上的单元测试工具。运行自动化让一个在 PHP 8 上运行的自动化测试套件将我们带入下一个兔子洞,作为在 PHP 世界中执行单元测试的事实上的工具;PHPUnit 通常每年都会发布一个大版本,每个主要版本都支持以前的 PHP 版本。它引入了重大更改,但由于 PHPUnit 9.3 正式兼容 PHP 8.0,正如我们上面提到的,无需担心!我们知道,WordPress 至少仍然支持 PHP 5.6。为了在 PHP 8.0 上运行测试,任何与 WordPress 相关的测试套件都需要与 PHPUnit 5 到 PHPUnit 9 完全兼容。实现这些工具以使测试套件兼容仍然需要花费精力和时间。
让测试在 PHP8 上运行 WordPress Core
WP Core 的测试目前正在通过并针对 PHP 8 运行。这些测试是在 PHPUnit 7.5 的 composer 安装版本上进行的。尽管 PHPUnit 9.3 是与 PHP 8 正式兼容的最古老的 PHPUnit 版本。最后一个问题已通过将选定数量的文件/类从 PHPUnit 9.3 复制到 WordPress 测试套件来解决,不包括 Composer 自动加载生成中的 PHPUnit 的本机类,支持在 WordPress 测试套件中使用 PHPUnit 9.3 的副本。这是可行的,但是,现在,我们将其称为 hacky 解决方案,除了当前可能需要的维护外,它在未来可能不可持续。为了测试的质量,一开始肯定很低,在大多数情况下都使用松散的类型检查。更深入地讲,解决此问题的 Trac 票证于 2016 年开放。考虑到 PHP 中更严格的类型遵守,此票证已恢复。已经进行了大量工作来缓解这种情况。在我们编写时,大约有 800 个实例(676 个 assertEquals() 添加到 96 个 assertNotEquals())。仍在使用松散的类型检查——从 8000 多个实例减少。部分地,在比较对象时,剩余的松散类型断言是合法的;在某种程度上,这些当然需要解决。但是,它目前会导致测试失败。最后这些强调了测试中的缺点,但更多的是,在被测试的代码中。
测试主题和插件
只有一小部分可用的插件是专业开发的,并且更受欢迎,并且已经进行了自动化测试。一般来说,这是令人担忧的,因为一个普通的 WordPress 网站肯定会运行近 19 或 20 个插件。相当多的网站推出了更多插件!对主题进行自动化测试就更罕见了。让这些测试套件在 PHP 8 上运行是一项挑战。而且在获得有关插件和主题与 PHP 8 兼容性的见解之前也是如此。但是,所拥有的插件/主题大多是可以预期最少 PHP 8.0 问题的插件/主题。我们惊呼是因为这样的主题/插件使用了专业的开发模型。更大的担忧是没有测试的大量测试和主题,因为在使用 PHP 8 运行时这些更容易出现问题。
对于确实有测试的主题和插件,主要有两种类型的测试,它们可能有也可能没有到位:
单元测试。“嘲笑” WP 以允许测试插件代码的独立测试。使用了像BrainMonkey和Mockery这样的流行框架。
集成测试。现在,集成测试是在我们运行测试套件之前 WordPress 本身加载的地方,它将使用 WPcore 代码并与 WP 测试套件集成。
集成测试
我们知道 WordPress 已决定坚持使用 PHPUnit 7.5。这意味着什么?好吧,对于主题和插件的集成测试,这些也将跳转到 PHPUnit 7.5(最大)。主题和插件要么必须复制 WP Core 中的 hack 以使其集成测试完美运行,要么必须使用WP Core 中的文件。但是,他们将不得不创建一个自定义自动加载器,因为无法使用相同的 Composer 自动加载生成黑客。如果无论如何都需要阻止加载 PHPUnit 原生文件,则必须确保在 Composer 自动加载文件之前引导此类自定义自动加载器。
单元测试
对于在 Mockery 或 BrainMonkey 帮助下的单元测试,PHPUnit > 8 是必需的,因为可用于 PHPUnit 7.x 的 Mockery 框架与 PHP 8.0 不兼容。因此,这些测试套件的可比性对于 PHPUnit 5 到 9 是强制性的,这无疑增加了另一个挑战。如何?当使用两种测试套件时,需要不同版本的 PHPUnit 来运行每个测试套件。为了加剧这种情况,插件通常会有一个提交的 composer.lock 文件,以确保它们的运行时依赖项处于它们可以依赖的给定版本,并且与 PHP 5.6 完全兼容。单元测试在某些时候,最后一部分是通过在 composer.json 文件中具有平台 php 5.6 类型的配置来强制执行的。这也意味着他们的开发依赖项 BrainMonkey、Mockery、PHPUnit也将锁定在与 PHP 5.6 兼容的版本。现在,这肯定会阻止在 PHP 8.0 上运行测试。除了更新 composer.lock 文件和 composer.json 之外,您还可以通过即时删除平台来克服这个问题。但是,这使得在 PHP 8.0 上运行测试对开发人员来说更加复杂,无论是在 CI 中还是在本地。
PHP 8 兼容性在大型 WordPress 网站上看起来有些棘手
通过调查 PHP 8 中的一系列重大更改,我们可以确认这很容易在网站上造成巨大的破坏,而破坏的原因尚不清楚。在某些时候,错误会发生在一个地方,但由不同地方的主题或插件生成,这肯定会使这些问题很难调试。无疑是一个积极维护的 WordPress 网站,并且有专门的专业开发人员团队为其提供支持。绝大多数 WordPress 网站都没有这样的奢侈,并且减轻这些网站上的兼容性问题肯定是具有挑战性的。
开发者需要多久更新一次?
PHP 每个版本的生命周期为 2 年,并且在这个时代修复了 bug。再增加一年,在此期间修补安全问题。PHP 7.4 于 2019 年 11 月到来。它是 PHP 7 的最终版本。这意味着 PHP 7.4 中的错误将被修复到 2021 年 11 月。安全问题将被修补到 2022 年 11 月。它将达到其“生命终结”在那个时间点。开发人员必须更新因此,硬性截止日期是 2022 年 11 月:此时所有 PHP 代码都需要与 PHP 8 兼容,否则就有被困在潜在易受攻击的 PHP 版本上的危险。
结论
PHP 8 将包含许多重大更改。我们已经在我们的报告中描述了这些变化的一个很好的范围,我们的专家认为除了更广泛的 WordPress 生态系统之外,这些变化将对 WordPress 产生更剧烈的影响。那些通常必须处理成为问题的警告。并且引入了几个错误,这可能很难处理。您可以在运行时检测到更高百分比的这些更改。解决所有这些兼容性问题是一项艰巨的任务。为此,您需要使用各种策略,从静态分析到自动化测试。它需要大量的时间+精力。您应该有权使用工具来完美地执行所有操作。对于必须支持各种 PHP 版本的项目,如 WordPress,在处理各种版本的分析工具时引入了一些额外的复杂性,正如我们上面讨论的那样。当然,由于 PHP 5 和 8 之间的运行时和语法差异如此之大,这变得相当困难。在 WordPress 上使用 PHP 8 好不好?其实不是这里的论据。这里唯一的结论是——这样做变得非常具有挑战性。此外,我们还考虑了覆盖问题和 WordPress 的 PHP 依赖关系。如果您想可靠地检测兼容性,那么高测试覆盖率证明是必要的。谈到 PHP 8,它甚至更重要,因为兼容性问题的数量比平时要多。其中很大一部分可以仅在运行时检测到。
那么,我们有什么建议呢?
如果检测到问题,则需要进行大量调试以找到问题的根源,无论是 WordPress、主题、插件,还是与 PHP 兼容性直接相关。依赖项几乎没有测试覆盖率并且很低。因此,很难惊呼什么是真正意义上的 WordPress 与 PHP 8 的核心兼容性。由于 PHP 8 如此专注于严格类型,WP 的类型不安全可扩展性系统变得更加容易受到问题的影响,可能导致插件在其他插件或 WP 本身中产生类型错误。我们通过对上个月的错误数据进行分析来对此进行测试。作为一个巨大的网站,我们认为它可能会强烈表明我们可以预期的各种问题。当然,我们发现几个警告会演变成 PHP 8 的错误。我们更愿意在这里做一个最后的说明。WordPress 并不是唯一可用的遗留代码库。它也不是唯一一个支持大量 PHP 版本的项目。本文中的信息也可能适用于其他项目。这篇文章的主要目的是告知并概述与 WP 中的 PHP 8 兼容性相关的挑战和问题。我们非常希望它能完美地达到这个目的。推荐相关阅读:《 WordPress网站如何拒绝SEO垃圾反向链接 》