PHP 7.4发布了! Badoo如何升级

今天终于有了PHP 7.4的发布!


它的新功能已经被反复描述 ,包括在Habré上 。 这些是箭头函数,类的键入属性以及更多的语法糖。 但最重要的是,由于性能原因,我们一直在等待一个新版本:在7.4版中,不仅出现了预加载,而且PHP本身变得更快。

坏消息(或好消息)-随着PHP 7.4的发布,对PHP 7.2的主动支持也停止了 。 他的最新版本于12月中旬。 我们已经在PHP 7.4上进行了很长时间的试验,最近我们正在积极地向PHP 7.4过渡,因为现在我们使用的是几乎不受支持的7.2版本。

恭喜大家期待已久的发行! 在下面,我将讨论一些有关我们如何升级到新版本的信息。

尽管我们拥有庞大的代码库,但我们在PHP中生活了13年。 我们已经多次不得不升级到新版本,并且过渡过程已经确立。

如果大大简化,我们可以区分几个步骤:

  • 我们确保单元测试开始在新版本上成功通过。
  • 对于所有代码更改,我们都使测试必须在新版本上运行(这样就不必重复步骤1,因为新代码不断写入,并且可能再次不兼容)。
  • 我们切换到新版本的开发平台,解决问题并在这种状态下生存了一段时间。
  • 重复此步骤进行。
  • 我们将其平稳地分布在不同的生产集群上。

我们在PHP资源库中的编辑


预紧力问题( 修复


这次,过程有所变化:自从我们等待预加载以来,我们从7月的7.4.0beta1版本开始执行部分工作。 结果,这导致我们花费了大量的调试时间,因为那时PHP 7.4完全是原始的。 但是,另一方面,结果是,我们发现了一个令人不快的错误,将其修复并将其发送给上游,这对整个社区都有帮助。

然后是时候进行测试了。

访问私有财产的问题( 修复


为了总体上运行测试,您需要更新PHPUnit,SoftMocks和PHP-Parser作为它们的一部分。 我们的代码库很大,即使要更新PHPUnit,也必须重写大量测试。

在设法运行测试之后,我们看到了一件非常奇怪的事情。 发生了很多崩溃并出现以下错误:

PHP Fatal error: Cannot access private property ClassLoader::$classMap in vendor/composer/ClassLoader.php 

对类的私有属性的访问仅在其内部进行,但是PHP报告一个错误:您不能像调用来自另一个类那样来访问私有属性。

由于复制不稳定,使问题变得复杂。 使用gdb进行的长时间调试表明,由于某种原因,实际上EG(fake_scope)没有访问该属性的类,但又有一个与此属性无关的类。

找到最小的重现情况(暂时需要三个类,一个自动加载器和一个Reflection),解决了问题的原因并开始在上游修复它之后,事实证明,此问题自PHP 7.3起就存在(很可能是,发生这种变化之后),整个世界与她在一起生活了一年,她没有打扰我们之前的任何人。

Badoo代码不兼容规则


现在,我们正在纠正PHP 7.4的所有代码不兼容性。 对我们而言,绝大多数不兼容性(一百多个位置,> 80%的不兼容性)是由于添加了错误“尝试访问类型为null / bool / int的值的数组偏移量”( 对应于RFC )引起的。 使用访问其他数据类型上的数组元素的语法时,会发生这种情况。

下面的示例很好地说明了该问题:

 $a = false; var_dump($a['somekey']); // PHP 7.3: // NULL // // PHP 7.4: // Notice: Trying to access array offset on value of type bool in Command line code on line 1 // NULL 

似乎在实际代码中不应出现这种情况,但是,如实践所示,这是一个相当普遍的情况:例如,函数可以在正常情况下返回数组,在出现错误的情况下返回false / null,并进一步获取有关false / null的堆栈信息丢失,并且这种情况不会单独处理。

这是在PHP中传播很少的但有用的更改:它使您可以发现代码中的许多潜在错误。

关于问题的第二次更新是对method_exists()工作方式的更改 。 顺便说一句,当前在发行说明或升级指南中没有关于它的信息。 其实质如下:

 class A1 {    private function priv() {} } class B1 extends A1 {} var_dump(method_exists(B1::class, 'priv')); // PHP 7.3: bool(true) // PHP 7.4: bool(false) 

同样,此功能很难在实际代码中实现。 但是,事实证明,我们在测试中无意间积极地利用了这一点。

当然,我们在不同程度上面临其他不兼容问题,包括与反射相关的众多更改( 示例一示例二 ),对hexdec()的更改等,甚至对ArrayAccess对象也禁止 array_key_exists(),通过Composer连接的各种依赖库中的不兼容性,甚至与各种奇特的东西(例如stream_set_option())已成为include上的流包装器所必需的不兼容。 但是总的来说,适应所有这些变化的成本无法与在非数组上使用数组语法的情况相提并论。

目前,我们已经完成了单元测试:它们完全通过了PHP 7.4。 我们正在进行API测试,并计划在今年年底之前开始切换不同的集群和环境。

我想邀请您参加此讨论以进行讨论:您是否已经尝试过PHP 7.4? 如果是这样,您的经历如何? 你要过马路吗?

Source: https://habr.com/ru/post/zh-CN477822/


All Articles