Rector 快速升级 PHP 8.4:一条 withPhpSets() 完成自动化改造
【免费下载链接】rectorInstant Upgrades and Automated Refactoring of any PHP 5.3+ code项目地址: https://gitcode.com/GitHub_Trending/re/rector
Rector(PHP 领域里的自动化重构工具)能在不改业务逻辑的前提下批量改写代码。本文带你用 Rector 完成 PHP 8.4 适配:只需在配置里写一行withPhpSets(php84: true),Rector 就会把隐式可空参数、round()取整常量、foreach查找这类老写法,一次性改写成 8.4 推荐的形式,并支持先 dry-run 预览再真正落盘。
Rector 如何知道要升级到 8.4
Rector 的升级能力不是靠正则匹配,而是先把 PHP 文件解析成语法树(AST,即把代码拆成"参数""函数调用""类"这些带类型的节点),再让一条条"规则"(Rector)逐个检查节点:命中就生成新节点,最后重新打印成代码。
它把不同 PHP 版本要改的写法整理成了"规则集"(Set)。其中 PHP 8.4 对应的集是 config/set/php84.php,目前包含 8 条规则:
ExplicitNullableParamTypeRector:参数类型补全(见下一节)RoundingModeEnumRector:round()的取整常量改枚举AddEscapeArgumentRector:CSV 函数补escape参数NewMethodCallWithoutParenthesesRector:(new Foo())->bar()去掉多余括号ForeachToArrayFind/FindKey/All/AnyRector:foreach循环改array_find/array_all/array_any等
每条规则都实现了provideMinPhpVersion(),Rector 会据此决定"当前目标版本下该不该出手",所以不会把 8.4 的语法塞给还在 8.1 的项目里。
三步完成基础配置:withPaths 加 withPhpSets
在目标项目里以开发依赖安装:
composer require rector/rector --devcomposer.json声明了bin/rector可执行入口,安装后即可用vendor/bin/rector调用。
接着在项目根目录建rector.php。它长什么样,仓库自带模板 templates/rector.php.dist 给了答案,在此基础上加一行withPhpSets()即可:
<?php use Rector\Config\RectorConfig; return RectorConfig::configure() ->withPaths([ __DIR__ . '/src', // 告诉 Rector 只动这些目录 ]) ->withPhpSets(php84: true); // 启用 PHP 5.3 → 8.4 的全部升级规则三个关键点:
withPaths()是白名单,没写进路径的文件一律不碰;withPhpSets()只应调用一次,php84: true表示"升级到 8.4",它会自动把 5.3 到 8.3 的历史规则一并打开(withPhpSets的签名在 src/Configuration/RectorConfigBuilder.php);- 如果你的
composer.json已声明"php": "8.4",可以直接不传参写->withPhpSets(),Rector 会自己读出来,升级目标始终跟着项目走。
它到底会改出什么效果
规则的实际输入输出,都写在每个 Rector 类的getRuleDefinition()里,前后对照最直观。
参数类型补全(rules/Php84/Rector/Param/ExplicitNullableParamTypeRector.php)——8.4 起隐式可空写法被弃用:
- function foo(string $param = null) {} + function foo(?string $param = null) {}round()取整常量改枚举(rules/Php84/Rector/FuncCall/RoundingModeEnumRector.php):
- round(1.5, 0, PHP_ROUND_HALF_UP); + round(1.5, 0, RoundingMode::HalfAwayFromZero);CSV 函数补escape参数(rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php):
- str_getcsv($string, separator: ',', enclosure: '"'); + str_getcsv($string, separator: ',', enclosure: '"', escape: '\\');foreach改数组函数(rules/Php84/Rector/Foreach_/ForeachToArrayFindRector.php)——"找到就 break"的循环,正是array_find的语义:
- $found = null; - foreach ($animals as $animal) { - if (str_starts_with($animal, 'c')) { - $found = $animal; - break; - } - } + $found = array_find($animals, fn ($animal) => str_starts_with($animal, 'c'));注意:array_find/array_all/array_any是 8.4 才有的函数,规则实现了RelatedPolyfillInterface接口——如果你的运行时还停在 8.3 以下,Rector 会提示你同时装 polyfill 包再启用这几条,避免改出运行不了的新代码。
先 dry-run 预览,再真正落盘
默认命令是process(见 src/Console/Command/ProcessCommand.php),所以可以直接跑vendor/bin/rector,但稳妥做法是先预览:
vendor/bin/rector process --dry-run--dry-run只打印 diff、不写回文件,你可以逐条确认每处改动。没问题后去掉参数执行,Rector 会输出类似35 files would have changed的汇总,真正的改写发生在这一轮。
如何验证转换结果
三个内置命令可以交叉验证:
# 配置本身有没有写错(拼写、重复调用 withPhpSets 等) vendor/bin/rector validate-config # 看当前配置实际启用了哪些规则,核对是否都是 PHP 8.4 预期内的 vendor/bin/rector list-ruleslist-rules的输出应当包含上面 8 条 Php84 规则,且没有混入 8.5+ 的语法改写——这就说明版本目标没写偏。
再落两个"护栏",避免升级跑偏:
- 跑完用
git diff扫一眼全部改动,确认只动了类型、函数调用这些"表面"结构,业务逻辑没变; - 把 Rector 接进 CI,让每次合并前都检查一次。仓库提供了
vendor/bin/rector setup-ci生成平台检查配置,模板在 templates/rector-github-action-check.yaml,改一下触发路径即可。
跑通这轮升级后,你手里其实拿到的是一个可复用的"版本流水线":下一次升到 8.5,只要把php84: true换成php85: true,同样的 dry-run、验证、合入流程再走一遍即可。
【免费下载链接】rectorInstant Upgrades and Automated Refactoring of any PHP 5.3+ code项目地址: https://gitcode.com/GitHub_Trending/re/rector
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考