Levels
A prepared set enables dozens of rules at once. On a legacy project that changes 90 % of files in one run, which nobody can review. Levels solve that: a level is the first N rules of a set, sorted from the safest to the most complex. Level 0 enables one rule, level 1 two rules, and so on. You raise the number by one, run Rector, review a small diff, merge, repeat.
vendor/bin/rector --dry-run
PHP Upgrade Level
The PHP upgrade sets are covered by withPhpLevel(). Start at 0:
<?php
use Rector\Config\RectorConfig;
return RectorConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
->withPhpLevel(0);
Rector only adds rules up to the PHP version in your composer.json, so the level never runs ahead of what your runtime supports. Once the level covers all the rules for your version, switch to withPhpSets() and keep it there. The step-by-step walkthrough is in New Project.
Type Coverage Level
Type coverage is one of the most influential metrics in a modern PHP project. We can have a high PHP version in composer.json, but our code can still be full of mixed types, giving us zero confidence. The type-coverage package measures it, Rector raises it.
The full set changes almost every file:
return RectorConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
+ ->withPreparedSets(typeDeclarations: true);
Use the level instead:
return RectorConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
- ->withPreparedSets(typeDeclarations: true);
+ ->withTypeCoverageLevel(0);
Only five files? We can do that in a day. We create a pull request, get a review, and merge. Then level 1. You get the idea.
Since Rector 2.2, there is a second level for docblock @param, @return and @var types, where native type hints are not possible, e.g. string[]:
return RectorConfig::configure()
->withTypeCoverageLevel(0)
->withTypeCoverageDocblockLevel(0);
Dead Code, Code Quality and Coding Style Levels
Done with types and reached 99 % type coverage? Move on to dead code removal, code quality and coding style, again by levels:
return RectorConfig::configure()
->withDeadCodeLevel(0)
->withCodeQualityLevel(0)
->withCodingStyleLevel(0);
Increase by 1, run Rector, create a pull request, get a review, merge. Once you reach the highest level, the level equals the whole set and you can move on to the next prepared sets.