大多数技术党都对 PHP 8.0 感到兴奋,当然,这次的变化是巨大的。每个人都会花一些时间来了解 PHP 8 的兼容性、配置、好处等,其中,出现的最大问题之一是——“WordPress 是否已经兼容 PHP 8,如果不兼容,那么需要采取什么措施。”
PHP 8 中有如此多的重大变化:但是为什么呢?
PHP 8 是 PHP 的一次重大更新,从最近的一系列小版本中删除主要版本中的负面内容是常见的做法。对于备受关注的 PHP 8,在之前的 7.* 版本中减少了几个重大更改。
因此,对于多年来一直精心更新、修复其贬低的 API 的项目,升级应该不难。说实话,与以前的 PHP 版本相比,PHP 7.* 版本经历了更大的弃用范围。
我们认为从 PHP 5.6 到 PHP 7 是一个非常简单的迁移,但从 7.x 到 8 可能会有些痛苦,特别是对于旧的代码库,包括 WordPress,以及几个可用的插件。
当然,对于类型良好的代码库或使用最新 PHP 版本的最新代码库,不会出现大问题。然而,事实是 WordPress 并不是这样的代码库。
WordPress 是否已经兼容 PHP 8?
说实话,WordPress 可能已经兼容 PHP 8,但封住这些话是不可能的。WordPress的目标是始终与最新版本的 PHP 兼容。但是,我们在本指南的后面深入分析了最大的问题。
我们在找到使用现有策略可以找到的大多数兼容性问题的完美解决方案方面做得非常出色。我们一定会更深入地研究那里的情况以及存在的问题。
即将发生哪些性能变化?
PHP 8 带来的主要潜在令人兴奋的功能是 JIT(即时)编译和调试。众所周知,PHP 是一种解释型语言,这意味着它在运行时会被翻译成机器代码。
JIT 会跟踪经常使用的代码,并致力于优化机器代码翻译,使其可重复使用。现在,这可以大大提高给定功能的性能。
各种语言(例如 JavaScript)中 JIT 的引入,在历史上引发了新应用的爆炸式增长。例如,在 Web 早期,在 JS 中运行的虚拟机是不可想象的。过去需要在服务器上安装模块的一些任务将通过核心 PHP 库来实现。
目前,像 WordPress 这样的 Web 应用的实际性能提升很小。除此之外,开发人员或普通 WordPress 用户还需要很长时间才能享受到这项新功能带来的好处。
还有其他一些新功能可以简化开发人员的生活;在可预见的未来,这些功能不太可能在 WP 主题和插件中使用,因为大多数功能会破坏与几个 WordPress 网站仍在使用的 PHP 早期版本的兼容性。
如何为您的 WordPress 网站更新 PHP?
在本指南中,我们将介绍如何方便地将 PHP 更新到最新版本,最重要的是,不会破坏您的 WordPress 网站。
如果您急于知道路径,那么只需检查您当前的 PHP 版本,然后将 WordPress 更新到最新版本。之后,安装“one.com PHP 扫描程序”并运行扫描以修复潜在问题。此外,将 PHP 更新到最新版本,并验证您的网站是否按预期运行。
让我们展示一下整个过程。
步骤 1:检查当前 PHP 版本
首先,您需要检查您当前使用的 PHP 版本。您可以从phpinfo 页面获取您网站当前 PHP 版本的信息。
如果您使用的是 PHP 7.3 或更高版本,则一切正常。对于使用 PHP 7.2 的用户,需要更新。请珍惜步骤 2。
步骤 2:将 WordPress 更新到最新版本
如果您真的想避免任何故障,请确保 WordPress 核心和所有插件和主题都已更新到最新版本。
- 登录到您的WordPress 管理员并单击仪表板>更新。
- 检查您是否安装了最新版本的 WordPress,以及所有主题和插件是否都是最新的。立即将您的 WordPress 更新到最新版本。
步骤 3:安装“one.com PHP扫描程序”。
- 在您的WordPress 管理员中,点击one.com >插件。
- 找到one.com PHP 扫描程序并点击立即安装。
- 现在,单击“激活”,并进入下一步。
步骤 4:运行扫描并修复潜在问题
- 在左侧菜单中,点击PHP 扫描器。
- 点击PHP 版本 7.4,然后点击“所有主题和插件”,然后点击开始扫描。
- 扫描完成后您就可以继续。
- 你可以得到三种结果:
–兼容= 意味着一切都好!
–警告= 这意味着它应该可以工作但可能会给即将推出的 PHP 版本带来问题。
–错误= 不太好,更新后肯定会引起问题。
修复任何读取错误的主题或插件,通过将其更新到最新版本或将其替换为提供相同功能的替代插件。
提示:我们建议您只使用那些定期更新且不会与最新版本的 WordPress 产生兼容性问题的插件。除此之外,删除任何不需要的插件以提高网站的性能也是一种很好的做法。
步骤 5:将PHP更新到8.0版本
现在您已准备好更新 PHP。我们建议您同时打开 PHP 错误消息。如果代码出现问题,您将看到错误消息,告诉您问题的原因以及问题的具体位置。
- 在控制面板中,返回PHP和数据库设置。
- 向下滚动到PHP 错误消息。
- 将错误消息设置为“开”后单击“更新”。
- 直接在下方更改版本并点击更新。
步骤 6:验证您的网站是否按预期运行。
现在,您已更新 PHP 版本,更改生效至少需要 20 分钟。如果您的网站有大量访问者,则时间范围可能会延长至几个小时。这就是我们建议在接下来的 24 小时内至少检查您的网站几次的原因。
如果您的网站没有按照预期运行,那么最有可能的问题出在您的主题或任何插件上。要找出导致问题的确切原因,请执行以下操作:
- 暂时切换到默认的 WordPress 主题,我们会说“Twenty Seventeen”。
- 选择所有已安装的插件并将其全部停用。
- 逐个重新启用主题和所有插件,并每次检查您的网站是否仍在运行。您可以通过这种方式找到罪魁祸首。
如果我们从技术角度进行讨论,那么当前版本的 WordPress 与备受讨论的 PHP 8 的兼容性与我们在新版本 PHP 出现之前所处的 WordPress 版本的兼容性处于相同的水平。
我们的测试非常全面,修复也非常细致,问题修复的级别与 WordPress 核心内的任何 PHP 兼容性修复一样高。但是,如果您不遵循本指南,您将无法理解兼容性挑战并从 PHP 8 中获得最大收益。
PHP 8 中包含的大量重大更改和各种更改,以及跨版本工具的一些额外复杂性,无疑使这一兼容性挑战比我们之前使用 PHP 之前版本时遇到的挑战更加严峻。本报告旨在解释同样的情况。
WordPress 和 PHP8 兼容性挑战
我们将向您展示一些可以部署的策略,以使现有代码库与 PHP 8 兼容。
- 静态分析工具(例如 PHPCompatibility)用于检测语法问题。
- 自动化测试以检测运行时问题。
- 手动测试以检测运行时问题。
根据测试套件的覆盖率以及语法更改和运行时间的比例,这些策略可以很好地修复代码库与新版本 PHP(目前正在讨论 PHP 8)的兼容性。
确实,就 PHP 8 和 WordPress 而言,还有一些额外的挑战,使得很难依赖这些策略来确保 WordPress 与 PHP 8 的完美兼容性。下面我们将报告我们为 WordPress 部署的策略并分享结果。
静态分析工具
由于 PHP 8.0 中一些变化的性质,使用静态分析可以检测到的问题有限。在这种情况下,静态分析试图超越其传统潜力并计划跟踪变量和常量的值以及运行时类型,这种扫描的结果肯定容易出现误报。
除此之外,PHP 兼容性是唯一用于查找 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 不使用类型声明,因此类型是根据找到的代码和文档块中显示的类型推断出来的,但这些问题仍然应该单独检查。
不管发现的问题中只有 1% 是正确的,错误数量仍会下降到约 450 个,这仍然需要处理。除此之外,还需要花费大量时间从误报中剔除真正的问题。
使用 PHPStan 扫描 WordPress
使用PHPStan进行扫描需要完全定制的规则集才能获得远程可用的结果,但事实证明它们充斥着一些误报,导致输出无法使用。
注意:我们并不是在批评 PHPStan 工具,但这很大程度上是由于 WordPress 几乎不使用类型声明,而另一方面,PHPStan 主要倾向于使用现代代码的项目,不是吗?
初始扫描包含最基本的配置,将产生 20,000 多个问题。使用高度定制的上述规则集进行扫描,专门针对 PHP 8 相关问题,仍然会在级别 5 处产生 580 个问题,并在级别 7 处产生额外的 2,150 个潜在问题。这些可能包含一些误报,但在级别 8 处会产生 380 个问题,并有类似的警告。
最近,我们打开了Trac ticket,以解决基于未知配置的一系列问题,但完全针对您传递的参数类型不匹配(级别 5)。Draft PR 可用于修复这些问题。
对此 PR 的初步评估表明,大多数建议的修复都会将变量转换为预期类型并隐藏问题,而不是通过正确检查来真正修复它们。如果这些更改没有伴随严格的单元测试,这会导致应用程序出现意外行为。除此之外,这肯定会增加后续调试错误的难度。
目前,尚未确认所提出的修复是否有必要,或者所发现的问题是否应被视为误报。
测试
由于 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 完全兼容。当然,工具就是为了帮助您实现这一点而构建的;实现这些工具以使测试套件兼容仍然需要花费精力和时间。
在 WordPress Core 的 PHP8 上运行测试
WP Core 的测试目前正在通过并针对 PHP 8 运行。这些测试是在 PHPUnit 7.5 的 Composer 安装版本上进行的。尽管 PHPUnit 9.3 是与 PHP 8 正式兼容的最老的 PHPUnit 版本。
最后一个问题已得到解决,方法是将选定数量的文件/类从 PHPUnit 9.3 复制到 WordPress 测试套件,从 Composer 自动加载生成中排除 PHPUnit 的原生类,支持在 WordPress 测试套件中使用来自 PHPUnit 9.3 的副本。目前,这种方法有效,但是,我们称其为一种黑客解决方案,除了目前可能需要的维护外,它在未来可能无法持续。
为了测试质量,这个标准一开始就很低,大多数情况下都采用松散类型检查。
更深入地讲,早在 2016 年就开出了一张 Trac 票来解决这个问题。考虑到 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 自动加载生成 hack。
如果无论如何都需要阻止加载 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 中还是在本地。
在大型 WordPress 网站上,PHP 8 兼容性看起来有些棘手
通过调查 PHP 8 中的一系列重大更改,我们可以确认这很容易导致网站出现严重故障,而故障原因却不明。在某些时候,错误会发生在一个地方,但由另一个地方的主题或插件生成,这肯定会使这些问题很难调试。
开发人员需要多长时间更新一次?
PHP 每个版本的生命周期为 2 年,在此期间会修复错误。 再增加一年,在此期间会修补安全问题。 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 版本的项目。本文中的信息也可能适用于其他项目。