Rector不是“一键升级”魔法棒,而是自动化PHP版本升级中重复易错的机械工作,需选对规则集、匹配运行环境,并直面原有类型隐患。

直接上结论:Rector 不是“一键升级”的魔法棒,而是把 PHP 版本升级中那些重复、易错、依赖 AST 理解的机械工作自动化——但前提是你得选对规则集、配对运行环境、并接受它会暴露原有代码里藏了多年的类型隐患。
怎么选对 up-to-php81.php 这类规则集
规则集不是越新越好。比如项目当前跑在 PHP 8.2,CI 也只支持到 8.2,却硬加 up-to-php83.php,Rector 就会往代码里塞 #[Override] 或只读类(readonly class),结果 php -l 直接报错。
- 先查真实环境:
php -v和php --modules,确认最低兼容版本 - 规则路径要写实:Rector 8.x 自带
up-to-php80.php~up-to-php83.php,但不带up-to-php85.php(除非你手动更新了 Rector 版本) - 别混用多个 level 规则集:
withSets([SetList::UP_TO_PHP_81, SetList::UP_TO_PHP_83])会触发Rule conflict: TypedPropertyRector vs AddArrayReturnTypeRector
--dry-run 显示改了 127 处,实际只生效 3 处?
这不是 Rector 抽风,大概率是路径或过滤配置没生效。
-
withPaths(['src'])不等于覆盖所有子目录——如果控制器在app/Http/Controllers,就得显式写进路径数组 -
withSkip()的路径必须和磁盘一致:src/Exceptions在 macOS 上有效,在 Windows 上得写src\Exceptions(Rector 不做路径归一化) - 某些规则有前置条件:比如
AddArrayReturnTypeRector只对已有完整 docblock 的函数生效;裸函数function foo() {}会被跳过
重构后跑出 Fatal error: Uncaught TypeError
这不是 Rector 改错了,是它把原来靠弱类型苟活的问题当场戳穿了。
立即学习“PHP免费学习笔记(深入)”;
- 典型场景:Rector 给构造函数加了属性提升
public function __construct(private string $name) {},但调用处是new User($_GET['name'] ?? null)——null传给string类型参数,PHP 8.0+ 立刻 fatal - 另一个常见坑:
AddVoidReturnTypeRector给无返回值函数加了: void,结果某处写了return $this;,PHP 8.1+ 拒绝执行 - 解决办法:先用
phpstan analyse或psalm --no-cache扫一遍类型问题,再让 Rector 动手;或者临时在withSkip()里排除高风险类
最常被忽略的一点:Rector 的重构效果高度依赖你是否已启用严格类型(declare(strict_types=1))。没开 strict 的项目,即使加了类型声明,运行时也不会报错,但 CI 或静态分析工具可能已经翻车——别等上线才发现。



















