Skip to main content
Version: v1

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 major release deprecated. Rector rewrites your code to replace them and moves it onto PHP 8.4 language features. It applies each refactoring across the whole codebase at once. Because Rector runs in every ahoy lint-be run and every CI build, the deprecations Drupal Rector covers are already fixed when a major upgrade starts.

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.

Vortex runs Rector as a regular code quality check:

  • ahoy lint-be reports the code Rector would change.
  • ahoy lint-be-fix applies the changes.
  • The lint job in CI fails while any change is pending.

Run ahoy lint-be-fix before a Drupal major upgrade to clear the remaining deprecations, and when you modernize legacy code in bulk.

Usage​

Check for violations​

Both commands run Rector as a dry run. The Ahoy command runs it last, after PHPCS and PHPStan. The Docker Compose command runs Rector alone. To check for code that Rector would change, run 1 of the following commands:

ahoy lint-be

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:

# Fix all back-end lint issues (Rector, then PHPCBF).
ahoy lint-be-fix

Cache management​

Rector caches parsed files 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.php configuration, such as its rules, skip list or paths
  • After you update the rector/rector or palantirnet/drupal-rector packages
  • 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 cli vendor/bin/rector process --clear-cache --dry-run

To clear the cache and apply changes, run 1 of the following commands:

ahoy 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/custom
  • web/themes/custom
  • web/sites/default/settings.php
  • web/sites/default/includes
  • tests

withPaths() leaves out scripts, which PHPCS and PHPStan check.

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.php constraint in composer.json allows, through withPhpSets(), which reads that constraint when called without an argument. The shipped constraint, >=8.4, resolves to PHP 8.4. The sets follow composer.json, so a PHP version change needs no edit to rector.php.
  • The Drupal sets from Drupal Rector, turned on by withSetProviders() and withComposerBased() and resolved from the installed drupal/core version, so the rules track core upgrades.
  • The codeQuality, codingStyle, deadCode, naming, privatization and typeDeclarations prepared 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, rector.php adds the DeclareStrictTypesRector rule and, when PHPUnit is selected, YieldDataProviderRector, which turns array-returning data providers into generators. withImportNames() is called with importNames: FALSE, so Rector adds no 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.

Ignore violations​

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 20 rules everywhere, based on the project's coding standards:

  • AddOverrideAttributeToOverriddenMethodsRector
  • ArrayToFirstClassCallableRector
  • CatchExceptionNameMatchingTypeRector
  • ChangeSwitchToMatchRector
  • CompleteDynamicPropertiesRector
  • DisallowedEmptyRuleFixerRector
  • InlineArrayReturnAssignRector
  • NewlineAfterStatementRector
  • NewlineBeforeNewAssignSetRector
  • NewlineBetweenClassLikeStmtsRector
  • PrivatizeFinalClassMethodRector
  • PrivatizeFinalClassPropertyRector
  • PrivatizeLocalGetterToPropertyRector
  • RemoveAlwaysTrueIfConditionRector
  • RenameForeachValueVariableToMatchExprVariableRector
  • RenameForeachValueVariableToMatchMethodCallReturnTypeRector
  • RenameParamToMatchTypeRector
  • RenameVariableToMatchMethodCallReturnTypeRector
  • RenameVariableToMatchNewTypeRector
  • SimplifyEmptyCheckOnEmptyArrayRector

The list skips RemoveUnusedPublicMethodParameterRector for the src/Hook classes of custom modules and themes, and StringClassNameToClassConstantRector for the settings includes. The list also skips 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.

Ignore 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.

➡️ See Continuous integration > Ignore tool failures