sandermuller / rector-preset
Shared Rector presets for apps and packages, versioned with Rector.
Requires
- php: ^8.4
- composer-runtime-api: ^2.2
- rector/rector: ~2.8.0
Requires (Dev)
- driftingly/rector-laravel: ^2.7.2
- hihaho/rector-rules: ^1.2.1
- laravel/pao: ^1.0
- laravel/pint: ^1.29
- mrpunyapal/rector-pest: ^0.2.17
- nunomaduro/collision: ^8.0
- orchestra/testbench: ^11.0
- pestphp/pest: ^5.0
- pestphp/pest-plugin-agent: ^5.0
- pestphp/pest-plugin-arch: ^5.0
- pestphp/pest-plugin-phpstan: ^5.0
- pestphp/pest-plugin-rector: ^5.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.0
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- sandermuller/boost-skills: ^2.27.0
- sandermuller/laravel-fluent-validation-rector: ^1.11
- sandermuller/package-boost-php: ^1.0
- spaze/phpstan-disallowed-calls: ^4.13
- stolt/lean-package-validator: ^6.0.1
- symfony/process: ^8.1
- symplify/phpstan-rules: ^14.19
- tomasvotruba/cognitive-complexity: ^1.2
- tomasvotruba/type-coverage: ^2.3
Suggests
- driftingly/rector-laravel: Enables the Laravel sets and skips when installed
- hihaho/rector-rules: Enables HihahoSetList::ALL when installed
- mrpunyapal/rector-pest: Enables the Pest code-quality and chain sets when installed
- pestphp/pest-plugin-rector: Enables the Pest coding-style set when installed
- sandermuller/laravel-fluent-validation-rector: Enables the FluentValidation sets when installed
Provides
None
Conflicts
- driftingly/rector-laravel: <2.7.2
- hihaho/rector-rules: <1.2.1
Replaces
None
README
Shared Rector presets for Laravel applications and Composer packages. A preset sets up the cache, the parallel workers, the prepared sets, the shared skips and the extension sets for the packages you have installed. Your rector.php keeps only what is specific to your project.
Installation
composer require --dev sandermuller/rector-preset:~2.8.0
Requires PHP 8.4 and rector/rector 2.8. The preset turns on the sets of the Rector extensions you have installed, so it refuses extension versions that fail on Rector 2.8: driftingly/rector-laravel below 2.7.2 and hihaho/rector-rules below 1.2.1.
Usage
For a Laravel application:
<?php declare(strict_types=1); use SanderMuller\RectorPreset\Preset; return Preset::app() ->withPhpSets(php85: true);
For a Composer package:
<?php declare(strict_types=1); use SanderMuller\RectorPreset\Preset; return Preset::package() ->withPhpSets(php84: true);
Each method returns Rector's own RectorConfigBuilder. Add your PHP set, configured rules and project skips to it:
return Preset::app(unskip: [Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class]) ->withPhpSets(php84: true) ->withSkip([__DIR__ . '/app/Models/Example.php']) ->withFluentCallNewLine(false);
What the presets set up
Both presets:
- Cache in
.cache/rector, and Rector's container cache in.cache/phpstan, the directory PHPStan uses astmpDir. The preset creates the directory when it is missing. - Parallel workers from the CPU count: 2 cores stay free locally, none on CI, at least 2 and at most 15 workers.
withMemoryLimit('3G'),withImportNames(),withAttributesSets()andwithFluentCallNewLine().- The
carbonset whennesbot/carbonis installed.
| Prepared set | app() |
package() |
|---|---|---|
deadCode, codeQuality, typeDeclarations, rectorPreset, phpunitCodeQuality |
on | on |
codingStyle, privatization, typeDeclarationDocblocks |
off | on |
Each prepared set is a parameter, for example Preset::app(codingStyle: true). instanceOf and earlyReturn are not: Rector 2.8 deprecated both sets and moved their rules into codeQuality.
Both presets skip TernaryToNullsafeCoalesceRector (its output fails PHPStan's nullsafe.neverNull) and ExplicitNullableObjectInstanceRector (on a nullable enum it lets deadCode delete reachable code).
package() also skips AddArrowFunctionReturnTypeRector, InlineArrayReturnAssignRector, PrivatizeFinalClassMethodRector, RemoveUselessParamTagRector and RemoveUselessReturnTagRector.
app() also skips ArgumentAdderRector, ClosureToArrowFunctionRector, PreferPHPUnitThisCallRector and RestoreDefaultNullToNullableTypePropertyRector, plus rector-laravel's ApplyDefaultInsteadOfNullCoalesceRector and ReplaceServiceContainerCallArgRector. It adds PreferPHPUnitSelfCallRector, and PrivatizeFinalClassPropertyRector while privatization is off.
A skip is added only when its rule class exists, so a Rector release that deletes a rule does not break your config. A skip is also left out when you turn off the set that registers its rule, because Rector warns on every run about a skipped rule that is never registered. The skips for PHP-version rules (TernaryToNullsafeCoalesceRector, ArgumentAdderRector, ClosureToArrowFunctionRector, RestoreDefaultNullToNullableTypePropertyRector) always stay, so call withPhpSets() in your rector.php.
Detection
With detect: true (the default), the preset looks at your folders and at the packages your project installs:
| When | The preset adds |
|---|---|
The folder exists: app, src, config, routes, database/factories, database/seeders, tests, workbench, bootstrap |
The folder to withPaths(). database/migrations is never scanned. bootstrap/cache, .cache and workbench/database/migrations are skipped. |
app(), or package(composerBased: true) |
withComposerBased() for the installed laravel/framework, symfony/framework-bundle, doctrine/orm and twig/twig |
phpunit/phpunit without pestphp/pest, in both presets |
withComposerBased(phpunit: true) |
driftingly/rector-laravel |
LARAVEL_CODE_QUALITY, LARAVEL_ARRAYACCESS_TO_METHOD_CALL, LARAVEL_CONTAINER_STRING_TO_FULLY_QUALIFIED_NAME, LARAVEL_FACADE_ALIASES_TO_FULL_NAMES, LARAVEL_COLLECTION |
pestphp/pest-plugin-rector |
CODING_STYLE |
mrpunyapal/rector-pest |
PEST_CODE_QUALITY, PEST_CHAIN, and PEST_LARAVEL with pestphp/pest-plugin-laravel |
hihaho/rector-rules |
HihahoSetList::ALL |
sandermuller/laravel-fluent-validation-rector |
FluentValidationSetList::ALL, POLISH and SIMPLIFY |
package() leaves the framework sets off. Rector picks those rules from the installed version, not from the range your package supports, so a package that supports Laravel 11 to 13 would get code that only works on Laravel 13. Pass composerBased: true when your package supports one major version. composerBased: false turns every composer-based set off, PHPUnit included.
An extension set is added only when its constant exists in the installed release, so an older extension loses that set instead of breaking your config.
To leave out one detected extension set, pass its constant to withoutSets. The other detected sets stay on:
return Preset::app(withoutSets: [Hihaho\RectorRules\Set\HihahoSetList::ALL]) ->withPhpSets() ->withRules([/* the hihaho rules you do use */]);
withoutSets throws an InvalidArgumentException for a set the preset did not detect, for example a prepared set such as SetList::DEAD_CODE. Turn those off with their parameter.
Your own withPaths() call replaces the detected paths. detect: false turns all detection off.
Parameters
Both methods take the same named parameters:
| Parameter | Default | Meaning |
|---|---|---|
projectRoot |
the Composer project root | The folder the paths and the cache resolve against |
containerCacheDirectory |
.cache/phpstan |
Relative to the project root, or absolute |
deadCode … phpunitCodeQuality |
see the table above | The prepared sets |
carbon |
null |
null turns it on when nesbot/carbon is installed |
unskip |
[] |
Rules to remove from the preset's skip list |
detect |
true |
Folder and package detection |
composerBased |
null |
null: frameworks in app(), PHPUnit only in package(); true: all; false: none |
withoutSets |
[] |
Detected extension sets to leave out |
Things to know
- Do not call
withCache()on the preset. Rector resets every cache argument you leave out, so you lose the container cache directory. Use thecontainerCacheDirectoryparameter. withPreparedSets()only adds sets, andwithSkip()only adds skips. To turn a preset set off, use its parameter. To remove a preset skip, useunskip.withPhpSets()is yours to call. Rector allows it only once.withTypeCoverageDocblockLevel()cannot be combined with thetypeDeclarationDocblocksset. Withpackage(), passtypeDeclarationDocblocks: false.
Versioning
The major and minor version follow Rector: 2.8.x requires rector/rector: ~2.8.0. The patch number belongs to this package. A patch release can change what the presets do, and its release notes list each change. Run rector --dry-run in CI to see the effect of an update. See PUBLIC_API.md.
Testing
composer test
License
MIT. See LICENSE.