mcpField
P
php-upgrade

php-upgrade

github.com/krzysztofsurdy开发3656 次安装1 天前更新
代码仓库

关于 php-upgrade

面向 PHP 应用维护者的升级技能,指导按版本顺序逐步升级。流程包括查阅迁移指南、兼容性审计、自动化代码修改、更新依赖和测试。

主要功能

  1. 01逐个 PHP 版本升级
  2. 02查阅官方迁移指南
  3. 03审计兼容性与依赖
  4. 04使用 Rector 执行代码转换
  5. 05部署前测试与验证

适用场景

  1. 01规划 PHP 小版本升级
  2. 02查找不兼容代码和扩展
  3. 03自动更新代码并检查回归问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/krzysztofsurdy/code-virtuoso --skill php-upgrade

安装后在 Claude Code 中输入/php-upgrade确认已加载。

附带文件references/upgrade-process.md

详细介绍

PHP 版本升级

每次只升级一个次版本,绝不跳过版本。每个步骤都会暴露在下一个版本中会变成错误的弃用项。每次升级都遵循相同的周期:审查、自动化、测试、部署。

核心原则

原则含义
先看变更日志每次升级前,获取该次升级对应的官方 php.net 迁移指南。切勿依赖此技能中的静态列表或模型记忆
一次升级一个版本按顺序从 8.2 -> 8.3 -> 8.4 -> 8.5 升级。跳过版本会导致无法隔离问题
升级前修复弃用项N 版本中的弃用项会在 N+1 版本中变成错误,因此必须修复
先自动化,再手动处理手动修改代码前,先运行 Rector 和 PHPCompatibility。它们能捕获 80% 以上的必要更改
用测试证明升级成功只有目标版本上的测试套件通过,升级才算完成
固定平台版本在 composer.json 中设置 config.platform.php,使其与最低部署目标一致

升级流程概览

阶段 0:阅读迁移指南

修改任何代码前,阅读当前版本到目标版本之间每次升级对应的官方指南。每次升级都有单独的页面,页面名称为目标版本对应的 migrationXY:

升级页面
7.4 -> 8.0https://www.php.net/manual/en/migration80.php
8.4 -> 8.5https://www.php.net/manual/en/migration85.php

每份指南都包含子页面:migrationXY.incompatible.php(不向后兼容的更改)、migrationXY.deprecated.php,以及(如果存在)migrationXY.removed-extensions.php。至少阅读前两个。

获取指南的方法:

  1. 使用 docs-lookup 技能。 对于 PHP,它会解析为 Context7 库 ID /websites/php_net_manual_en。查询“从 PHP X.Y 迁移到 PHP X.Z、不向后兼容的更改和弃用的功能”
  2. **备用方法:**直接获取上述 php.net URL,或向用户索要发行说明
  3. 记录适用项。 在代码库中使用 grep 搜索列出的每个项目,并保留搜索结果,作为自动化和手动修复步骤的工作清单

“按版本列出的已知陷阱”表格可作为 grep 搜索的起点,但不能替代指南。

阶段 1:审查

修改任何代码前,先了解升级的工作量。

  1. 使用目标版本运行 PHPCompatibility,找出不兼容的代码。最后一个稳定版本(9.3.5,2019 年发布)早于 PHP 8.1,缺少大多数较新的规则。请安装 10.0.0-alpha2 或更高版本,该版本包含 PHP 8.x 代码嗅探器,并先阅读其升级说明
  2. 使用目标 PHP 二进制文件运行 php-parallel-lint,以发现语法错误
  3. 运行 composer outdated,检查所有依赖项是否支持目标版本
  4. 对照代码检查阶段 0 中列出的项目
  5. 检查 PHP 扩展的兼容性(ext-intl、ext-mbstring 等)
阶段 2:自动化

使用 Rector 批量应用代码转换。

// rector.php
use Rector\Config\RectorConfig;

return RectorConfig::configure()
    ->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
    ->withPhpSets(php85: true);  // adjust to target version

始终先进行试运行:

vendor/bin/rector process --dry-run

检查更改,然后应用:

vendor/bin/rector process

将 Rector 更改与手动修复分别提交,以保持 git 历史整洁。

阶段 3:更新依赖项
  1. 在 composer.json 中更新 PHP 版本约束:"php": ">=8.5"
  2. 更新 config.platform.php,使其与目标版本一致
  3. 运行 composer update 并解决冲突
  4. 根据需要更新 PHP 扩展
阶段 4:测试和部署
  1. 在新 PHP 版本下运行完整测试套件
  2. 运行静态分析(PHPStan/Psalm)
  3. 部署到预发布环境并验证
  4. 部署后监控生产日志中的弃用提示

有关工具配置、CI 流水线设置和 Docker 注意事项,请参阅升级流程参考。


工具

工具用途使用时机
Rector基于 AST 的自动代码转换审计后的第一步。处理大多数机械性变更
PHPCompatibility用于跨版本兼容性的 PHP_CodeSniffer 规则集审计阶段。在开始前识别所有不兼容代码
php-parallel-lint并行语法检查(比串行快约 20 倍)审计阶段。捕获新版本下的语法错误
PHPStan/Psalm静态分析验证阶段。转换后捕获类型错误
symfony/phpunit-bridge在测试输出中汇总弃用项持续进行。跟踪升级期间的弃用项数量

各版本间已知陷阱

最容易导致实际升级失败的项目。每一项均摘自对应版本升级路径的 php.net 迁移页面。其他内容请获取完整指南(阶段 0)。

升级路径陷阱
7.4 -> 8.00 == "abc" 现在结果为 false(数字会转换为字符串)。对数组、资源或对象进行算术运算会抛出 TypeError。@ 不再屏蔽致命错误。读取未定义的变量、键和属性会产生警告。使用未定义的裸常量会抛出 Error。create_function() 和 each() 已移除。. 的优先级现在低于 + 和 -
8.0 -> 8.1向不可为 null 的内置参数传递 null 已弃用。会损失精度的浮点数到整数转换已弃用。未实现 __serialize() 和 __unserialize() 的 Serializable 已弃用。继承的方法与父类共享 static 变量。向 false 追加内容已弃用。写入整个 $GLOBALS 数组会报错
8.1 -> 8.2动态属性已弃用(请声明属性,或添加 #[\AllowDynamicProperties])。"${var}" 插值已弃用。utf8_encode() 和 utf8_decode() 已弃用。"self::method" 这类可调用对象已弃用。strtolower()、ucfirst() 等函数不再受区域设置影响
8.2 -> 8.3对空字符串或非字母数字字符串使用 ++ 和 -- 已弃用。不带参数的 get_class() 已弃用。日期扩展错误现在使用 DateError 和 DateException 类型,而不是警告。带有静态属性的 Trait 会重新声明父类的属性。对空数组使用负索引会使下一个键变为 n+1
8.3 -> 8.4隐式可为 null 的参数(T $x = null)已弃用,请使用 ?T。E_STRICT 以及使用 E_USER_ERROR 的 trigger_error() 已弃用。exit() 会进行类型检查。IMAP、OCI8、PDO_OCI 和 PSpell 已移至 PECL。GMP 为 final。名为 _ 的类已弃用。0 ** -1 已弃用
8.4 -> 8.5Opcache 始终内置,zend_extension=opcache.so 现在会发出警告,因此请从 php.ini 和 Docker 配置中移除它。反引号运算符、(boolean)、(integer)、(double) 和 (binary) 强制转换、null 数组偏移以及 case x; 已弃用。__sleep() 和 __wakeup() 已软弃用。disable_classes INI 已移除。Trait 会在父类之前绑定。将无法容纳在 int 中的浮点数强制转换为 int 现在会发出警告

常见陷阱

陷阱影响预防措施
跳过版本无法确定哪些更改导致了哪些问题始终一次升级一个版本
忽略弃用警告弃用功能会在下一个版本中变成致命错误升级前修复所有弃用问题
不检查依赖项第三方软件包可能不支持目标版本开始前运行 composer outdated 并检查支持情况
使用 --ignore-platform-reqs绕过安全检查并导致运行时错误绝不要使用。应改为修复实际的约束
未锁定 config.platform.php本地 PHP 与生产环境不同,导致安装不匹配始终将其设置为与生产环境一致
大批量运行 Rector 且不审查Rector 在边缘情况下可能会进行错误转换始终先试运行、审查更改,并分小批次运行
忘记 PHP 扩展扩展会改变行为,或在不同版本间被弃用升级前审查所有必需的扩展

快速参考:升级检查清单

  • 查阅目标版本的 php.net 迁移指南
  • 针对目标版本运行 PHPCompatibility 扫描
  • 使用目标 PHP 二进制文件运行 php-parallel-lint
  • 确认所有 Composer 依赖项都支持目标版本
  • 配置并运行 Rector,设置目标版本(先试运行)
  • 审查并提交 Rector 的更改
  • 为剩余问题应用手动修复
  • 更新 composer.json 中的 PHP 约束和 config.platform.php
  • 运行 composer update
  • 在目标 PHP 版本上运行完整测试套件
  • 运行静态分析(PHPStan/Psalm)
  • 部署到预发布环境并验证
  • 部署到生产环境并监控日志

参考文件

参考资料内容
升级流程工具配置、CI 流水线设置、Docker 策略和分步命令

与其他技能的集成

情况推荐技能
查找某个版本跳转的迁移指南使用 docs-lookup 技能
同步升级 Symfony 和 PHP使用 frameworks/symfony/ 中的 symfony-upgrade 技能
PHP 升级后更新 Composer 依赖项使用 composer-dependencies 技能
改进 PHP 代码模式(DTO、枚举、严格类型)从 dirnbauer/webconsulting-skills 或 netresearch/php-modernization-skill 安装 php-modernization
升级后运行静态分析testing

评论

支持 Markdown