Core sets like Twig, Symfony, or Doctrine are based on specific versions of installed packages in /vendor:
use Rector\Config\RectorConfig;
return RectorConfig::configure()
->withComposerBased(twig: true);
If you use Twig 2, Rector will load sets for Twig 2. Once you bump to Twig 3 in composer.json, Rector will automatically load new rules for Twig 3.
These sets are configured via classes that implement SetProviderInterface. Let's say you want to create a custom rule set for your Laravel community. Once set up, let us know, and we can add it to the Rector withComposerBased() method.
Let's take it step by step.
LaravelSetProvider class that implements SetProviderInterfaceuse Rector\Set\Contract\SetInterface;
use Rector\Set\Contract\SetProviderInterface;
use Rector\Set\ValueObject\Set;
final class LaravelSetProvider implements SetProviderInterface
{
/**
* @return SetInterface[]
*/
public function provide(): array
{
return [];
}
}
ComposerTriggeredSet objects to the provide() methodWhat is the ComposerTriggeredSet object for? It connects to a specific package + version with a path to the rule set:
namespace Rector\Set\ValueObject;
use Rector\Set\Contract\SetInterface
final class ComposerTriggeredSet implements SetInterface
{
public function __construct(
private string $groupName,
private string $packageName,
private string $version,
private string $setFilePath
) {
}
// ...
}
$groupName is key in ->withComposerBased():$packageName is the composer package name.$version is the minimal version to trigger the set$setFilePath is the path to the Rector config with rules as we know itLet's add objects for Laravel 10 and 11:
use Rector\Set\Contract\SetInterface;
use Rector\Set\Contract\SetProviderInterface;
use Rector\Set\ValueObject\ComposerTriggeredSet;
use Rector\Set\ValueObject\Set;
final class LaravelSetProvider implements SetProviderInterface
{
/**
* @return SetInterface[]
*/
public function provide(): array
{
return [
new ComposerTriggeredSet(
'laravel',
'laravel/framework',
'10.0',
__DIR__ . '/../../config/sets/laravel10.php'
),
new ComposerTriggeredSet(
'laravel',
'laravel/framework',
'11.0',
__DIR__ . '/../../config/sets/laravel11.php'
),
// ...
];
}
}
rector.phpuse Rector\Config\RectorConfig;
return RectorConfig::configure()
->withComposerBased(laravel: true);
If your parameter is missing, send us a PR to enable it.
And we're done. Now, Rector will load the laravel10.php rules for Laravel 10 and laravel11.php rules for Laravel 11.
You can be creative with SetListProvider and define a rule for more specific packages like illuminate/container. That way, we handle complexity for Rector end-users, and all they have to do is add a single parameter to the rector.php config.