Rector - instant upgrades and automated refactoring
The Rector project describes the tool as follows:
Rector instantly upgrades and refactors the PHP code of your application.
Every Drupal major release removes the APIs that the previous one deprecated. Rector rewrites your code to replace them, moves it onto PHP 8.4 language features, and applies the same refactorings across the whole codebase at once. Keep it running, and a major upgrade starts with the deprecations that Drupal Rector covers already fixed.
Vortex comes with a pre-configured Rector configuration for Drupal projects, based on the configuration provided by Drupal Rector.
This page is for developers who keep custom code current with Drupal and PHP. It shows how to run Rector and clear its cache, which rule sets Vortex enables, and how to skip a rule or a file.
Many projects run Rector ad hoc, for a single round of bulk refactoring.
Vortex runs it as a regular code quality check instead: ahoy lint-be
reports the code Rector would change, ahoy lint-be-fix applies the
changes, and the lint job in CI fails while any change is pending. Run it
by hand before a Drupal major upgrade to clear the remaining deprecations,
and when you refactor legacy code to modernize it in bulk.
Usage
Check for violations
ahoy lint-be runs Rector last, after PHPCS and PHPStan, while the Docker
Compose command runs Rector alone. To check for code that Rector would
change, run 1 of the following commands:
- Ahoy
- Docker Compose
ahoy lint-be
docker compose exec cli vendor/bin/rector --dry-run
Confirm that Rector found nothing to change: the output ends with
[OK] Rector is done!. When Rector would change files, it prints a diff
for each file and exits with code 2, which fails the check.
Fix violations
To apply the changes, run 1 of the following commands:
- Ahoy
- Docker Compose
# Fix all back-end lint issues (Rector, then PHPCBF).
ahoy lint-be-fix
docker compose exec cli vendor/bin/rector process
Cache management
Rector caches parsed file information and analysis results in the system
temp directory, /tmp/rector_cached_files inside the CLI container, so
later runs reuse the results for files that haven't changed.
Clear the cache in any of the following cases:
- After you change the
rector.phpconfiguration, such as its rules, skip list, or paths - After you update the
rector/rectororpalantirnet/drupal-rectorpackages - After you switch to a Git branch with a different Rector configuration
- Whenever the results look stale
To clear the cache and check for violations, run 1 of the following commands:
- Ahoy
- Docker Compose
ahoy cli vendor/bin/rector process --clear-cache --dry-run
docker compose exec cli vendor/bin/rector process \
--clear-cache --dry-run
To clear the cache and apply changes, run 1 of the following commands:
- Ahoy
- Docker Compose
ahoy cli vendor/bin/rector process --clear-cache
docker compose exec cli vendor/bin/rector process --clear-cache
Configuration
See the Rector documentation.
All global configuration lives in the
rector.php file.
Rector processes the following paths, which withPaths() in rector.php
lists:
web/modules/customweb/themes/customweb/sites/default/settings.phpweb/sites/default/includestests
Unlike PHPCS and PHPStan, Rector leaves the scripts directory alone.
Config sets
Rector provides config sets that each turn on a group of related rules. Vortex enables the following sets:
- The PHP sets up to the lowest PHP version that the
require.phpconstraint incomposer.jsonallows, throughwithPhpSets()called without an argument. The shipped constraint,>=8.4, resolves to PHP 8.4. The sets followcomposer.json, sorector.phpneeds no change when you move to a new PHP version. - The Drupal sets from Drupal
Rector, resolved from the
installed
drupal/coreversion, so the rules track core upgrades without changes torector.php. - The
codeQuality,codingStyle,deadCode,naming,privatization, andtypeDeclarationsprepared sets. - The Behat attribute sets, which convert Behat annotations to PHP 8 attributes. They ship only when Behat is selected during installation.
On top of the sets, it adds the DeclareStrictTypesRector rule and, when
PHPUnit is selected, YieldDataProviderRector, which turns array-returning
data providers into generators. It also leaves class names unimported, so
Rector doesn't add use statements to the files it changes.
To adjust the sets, edit the withPhpSets(), withAttributesSets(), and
withPreparedSets() calls in rector.php. The Set
Lists page describes the
available sets, and the Find a Rector
rule page lists the
individual rules.
Ignoring
For every way to skip a rule or a path, see the Rector configuration documentation.
To skip a rule across the project, add it to withSkip() in the
rector.php file:
->withSkip([
SimplifyIfReturnBoolRector::class,
])
The shipped withSkip() list already skips the following 22 rules
everywhere, based on the project's coding standards:
AddOverrideAttributeToOverriddenMethodsRectorArrayToFirstClassCallableRectorCatchExceptionNameMatchingTypeRectorChangeSwitchToMatchRectorCompleteDynamicPropertiesRectorDisallowedEmptyRuleFixerRectorInlineArrayReturnAssignRectorNewlineAfterStatementRectorNewlineBeforeNewAssignSetRectorNewlineBetweenClassLikeStmtsRectorPrivatizeFinalClassConstantRectorPrivatizeFinalClassMethodRectorPrivatizeFinalClassPropertyRectorPrivatizeLocalGetterToPropertyRectorRemoveAlwaysTrueIfConditionRectorRenameForeachValueVariableToMatchExprVariableRectorRenameForeachValueVariableToMatchMethodCallReturnTypeRectorRenameParamToMatchTypeRectorRenamePropertyToMatchTypeRectorRenameVariableToMatchMethodCallReturnTypeRectorRenameVariableToMatchNewTypeRectorSimplifyEmptyCheckOnEmptyArrayRector
It also skips StringClassNameToClassConstantRector for the settings
includes, and the vendor and node_modules directories.
To skip all Rector rules for a file, add its path to withSkip():
->withSkip([
'file.php',
'*/other_file.php',
])
To skip a specific rule for a file, map the rule to the file's path in
withSkip():
->withSkip([
SimplifyIfReturnBoolRector::class => ['file.php'],
])
Rector doesn't support ignoring code blocks.
Continuous integration
Rector runs in the lint job of the continuous integration
pipeline and fails the build on
violations.
Ignoring failures
To let the build pass anyway, set the VORTEX_CI_RECTOR_IGNORE_FAILURE CI
variable to 1. Rector still runs and prints the changes it would make in
the job log, so you can see what you're letting through.