最近我们团队把一个跑了五年的老项目,从PHP 7.4迁移到了PHP 8.5。整个过程花了一个多月,踩了不少坑,也积累了一些经验。
这篇文章我想分享一下这次迁移的完整过程,包括为什么要迁移、迁移前的准备、迁移中遇到的问题和解决方案,以及迁移后的效果。如果你也有老项目需要升级PHP版本,希望这篇文章能帮到你。
为什么要迁移
先说说为什么要从PHP 7.4迁移到8.5。
第一个原因是PHP 7.4已经停止维护了。PHP 7.4在2022年底就停止了安全更新,继续使用有安全风险。虽然我们的项目运行得很稳定,但用一个不再维护的版本,总是心里不踏实。
第二个原因是性能提升。PHP 8.x的性能比7.4有明显提升,特别是JIT编译器加入之后,数值计算和字符串处理的性能提升很大。我们的项目有一些计算密集的逻辑,升级之后性能提升明显。
第三个原因是新特性。PHP 8.x加入了很多有用的新特性,比如命名参数、联合类型、匹配表达式、构造器属性提升、枚举等。这些特性能让代码更简洁、更安全、更易维护。
第四个原因是生态。越来越多的第三方库开始放弃对PHP 7的支持,只支持PHP 8。如果不升级,很多新的库和框架就用不了,技术栈会越来越落后。
综合这些原因,我们决定把项目迁移到PHP 8.5。
迁移前的准备
迁移之前,我们做了充分的准备工作。
第一步是评估项目的情况。我们统计了项目的代码量、依赖的第三方库、使用的PHP特性。我们用了一些工具来扫描代码,找出可能不兼容的地方,比如被废弃的函数、不兼容的语法、依赖的库是否支持PHP 8。
第二步是搭建测试环境。我们在测试服务器上装了PHP 8.5,把代码部署上去,看看能不能正常运行。这一步发现了很多问题,比如扩展不兼容、配置不一样、代码报错等。
第三步是补测试。老项目的测试覆盖率很低,很多核心逻辑都没有测试。迁移之前,我们花了两周时间,给核心模块补了单元测试和集成测试。有了测试,迁移的时候就放心多了,改完代码跑一遍测试,就知道有没有破坏功能。
第四步是制定迁移计划。我们没有打算一次性迁移完,而是制定了一个分阶段的计划。先在测试环境跑通,然后在预发布环境验证,最后再切到生产环境。每个阶段都有明确的验收标准和回滚方案。
迁移中遇到的问题
迁移过程中遇到了不少问题,这里挑几个典型的说说。
第一个问题是扩展不兼容。我们的项目依赖了几个PHP扩展,其中有一个扩展在PHP 8.5上没有编译通过。查了一下,这个扩展已经很久没更新了,官方不支持PHP 8。我们的解决方案是,找了一个替代的扩展,功能差不多,而且支持PHP 8。改了调用的代码,花了几天时间适配。
第二个问题是废弃的函数和特性。PHP 8.x废弃了一些函数和特性,比如each()函数、create_function()、可变参数的某些用法等。我们的代码里有不少这些废弃的用法,编译器会报deprecated警告。我们用工具批量扫描了这些问题,然后逐个修复。大部分修复很简单,替换成新的写法就行。
第三个问题是类型系统更严格了。PHP 8.x的类型检查比7.4严格很多,很多在7.4里能跑的代码,在8.5里会报类型错误。比如,函数声明了参数类型,但传进去的是null,7.4里可能会自动转换,8.5里会直接报错。我们花了不少时间来修复这些类型问题,给函数加了正确的类型声明,处理了null的情况。
第四个问题是第三方库的版本冲突。很多第三方库的旧版本不支持PHP 8,需要升级到新版本。但新版本可能有breaking change,API变了,需要改调用代码。我们一个库一个库地升级,改完跑测试,确保功能正常。这个过程比较繁琐,但不算太难。
第五个问题是JIT的配置。PHP 8.5的JIT编译器需要手动配置,而且有不同的模式。我们最开始用默认配置,发现性能提升不明显。后来研究了一下JIT的配置参数,调整了之后,性能提升了不少。特别是在计算密集的场景下,JIT的效果很明显。
迁移的策略
我们的迁移策略是渐进式的,不是一刀切。
首先,我们让代码同时兼容PHP 7.4和8.5。在迁移的过程中,我们改的代码都要保证在两个版本下都能跑。这样我们可以随时在两个版本之间切换,降低风险。
然后,我们先在测试环境用PHP 8.5跑,发现问题就修。等测试环境稳定了,再在预发布环境用8.5跑,让测试团队做全面的回归测试。
最后,生产环境的切换,我们用了灰度发布。先把一小部分流量切到PHP 8.5,观察一段时间,没问题再逐步扩大比例。如果出了问题,可以随时切回7.4。整个切换过程花了一周时间,非常平稳。
这种渐进式的迁移策略,风险很低,而且给了我们足够的时间来发现和解决问题。
PHP 8.5新特性的应用
迁移到8.5之后,我们开始逐步应用新特性,让代码更好。
第一个用的是构造器属性提升。以前写一个值对象,要声明属性、写构造函数、赋值,很啰嗦。用构造器属性提升,在构造函数的参数前加修饰符,就能自动创建属性并赋值,代码简洁了很多。
第二个用的是匹配表达式。以前的switch语句很啰嗦,而且容易漏写break。用match表达式,代码更简洁,而且是表达式,可以直接赋值,用起来很舒服。
第三个用的是联合类型。以前一个参数可能接受多种类型,只能不写类型或者用PHPDoc注释。现在可以直接写联合类型,比如int|string,编译器会做类型检查,代码更安全。
第四个用的是枚举。以前我们用类常量来表示枚举值,很不优雅。现在有了原生的枚举类型,代码更清晰,类型更安全。
第五个用的是命名参数。调用函数的时候,可以指定参数名,不用按顺序传。这样代码的可读性更好,特别是参数多的时候,不用去查每个参数是什么意思。
这些新特性的应用,让我们的代码更简洁、更安全、更易维护。虽然不是必须的,但用了之后就回不去了。
迁移后的效果
迁移完成之后,效果还是很明显的。
第一个是性能提升。我们做了基准测试,同样的接口,PHP 8.5比7.4快了大约20%。特别是在计算密集的场景下,开启JIT之后,性能提升了30%以上。服务器的CPU使用率下降了,响应时间也缩短了。
第二个是代码质量提升。迁移过程中,我们修复了很多潜在的bug,比如类型错误、空指针、废弃函数的使用等。补了测试之后,代码的可维护性也提升了。新特性的应用,让代码更简洁清晰。
第三个是开发效率提升。PHP 8.5的新特性让写代码更舒服,IDE的提示也更准确。而且很多新的库和框架都支持PHP 8了,我们可以用上更好的工具。
第四个是团队士气提升。用新版本的技术,团队成员都很有热情,学习新特性的积极性很高。而且摆脱了老版本的束缚,大家都觉得技术栈更现代了。
给准备迁移的朋友的建议
最后给准备迁移PHP版本的朋友几个建议。
第一,不要急。迁移是一个过程,不是一天两天能完成的。给自己足够的时间,做好计划,一步步来。
第二,先补测试。没有测试的迁移就是赌博。迁移之前,一定要给核心逻辑补好测试,这样改代码的时候才有底。
第三,用工具辅助。有很多工具可以帮你扫描不兼容的代码,比如PHP_CodeSniffer、PHPStan、Rector等。善用这些工具,能节省大量时间。
第四,渐进式迁移。不要一次性切换,分阶段来,先测试环境,再预发布,最后生产。用灰度发布,降低风险。
第五,关注扩展和依赖。迁移之前,先确认所有依赖的扩展和第三方库都支持新版本。如果有不支持的,提前找替代方案。
第六,利用新特性。迁移不是为了升级而升级,升级之后要用上新特性,让代码更好。但也不要为了用新特性而用,适合的场景才用。
写在最后
从PHP 7.4迁移到8.5,花了一个多月的时间,踩了不少坑,但也收获很多。
PHP这几年的进步很大,从7.4到8.5,不管是性能还是语言特性,都有了质的飞跃。如果你还在用老版本的PHP,我建议尽早升级。虽然迁移过程有点麻烦,但升级之后的收益是实实在在的。
技术的发展就是这样,不进则退。保持技术栈的更新,不仅是为了用新特性,更是为了安全、性能和可维护性。
最后用一句话来结束这篇文章:"迁移不是目的,而是手段。通过迁移,让系统更稳定、更高效、更易维护,才是真正的目的。"
愿每一个PHP开发者,都能顺利完成版本升级,用上更好的技术。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录