driftingly/rector-laravel
Rector extension for Laravel that applies automated refactors and upgrade rules based on your composer.json or selected Laravel version sets. Includes rules for core Laravel and first‑party packages like Cashier and Livewire.
Installation:
composer require --dev driftingly/rector-laravel
Basic Configuration (rector.php):
use Rector\Config\RectorConfig;
use RectorLaravel\Set\LaravelSetProvider;
return RectorConfig::configure()
->withSetProviders(LaravelSetProvider::class)
->withComposerBased(laravel: true);
This auto-detects your Laravel version from composer.json and applies the correct upgrade rules.
First Use Case: Run Rector to upgrade from Laravel 11 → 12:
vendor/bin/rector process src --dry-run
Review changes before committing (--dry-run skips actual file modifications).
dev-main.RectorLaravel\Set\LaravelLevelSetList for version-specific rules (e.g., UP_TO_LARAVEL_130).LaravelSetList for code quality improvements (e.g., LARAVEL_COLLECTION, LARAVEL_CODE_QUALITY).Version Upgrade Workflow:
--dry-run to preview changes:
vendor/bin/rector process src --dry-run --set=LaravelLevelSetList::UP_TO_LARAVEL_130
vendor/bin/rector process src --set=LaravelSetList::LARAVEL_CODE_QUALITY
Incremental Refactoring:
->withComposerBased(laravel: true, packages: ['livewire/livewire'])
->withSets([
LaravelSetList::LARAVEL_STATIC_TO_INJECTION, // Replace facades with DI
LaravelSetList::LARAVEL_COLLECTION, // Optimize collections
])
Testing Integration:
- name: Run Rector
run: vendor/bin/rector process src --set=LaravelSetList::LARAVEL_TESTING
--diff flag to generate Git diffs for PRs:
vendor/bin/rector process src --diff > rector-changes.diff
composer make:rule -- MyCustomRule
Example: Convert Route::get() to controller actions:
// In `rector.php`
->withRules([
\RectorLaravel\Rector\StaticCall\RouteActionCallableRector::class,
])
->withPaths([
__DIR__.'/src',
__DIR__.'/app',
])
->withExcludedPaths([
__DIR__.'/tests',
__DIR__.'/vendor',
])
False Positives:
--dry-run.RouteActionCallableRector might fail if controller namespaces are non-standard.
Fix: Configure the NAMESPACE option:
->withConfiguredRule(RouteActionCallableRector::class, [
'NAMESPACE' => 'App\\Http\\Controllers\\',
])
Breaking Changes:
LARAVEL_STATIC_TO_INJECTION) require manual DI setup in constructors.vendor/bin/rector process src --set=LaravelSetList::LARAVEL_FACADE_ALIASES_TO_FULL_NAMES
Performance:
--parallel for multi-core processing:
vendor/bin/rector process src --parallel
Verbose Output: Enable debug mode to trace rule execution:
vendor/bin/rector process src --verbose
Look for skipped files or failed rules.
Rule-Specific Debugging:
rector.log for detailed errors.WhereToWhereLikeRector fails, verify PostgreSQL vs. MySQL syntax:
->withConfiguredRule(WhereToWhereLikeRector::class, [
'USING_POSTGRES_DRIVER' => true,
])
Skipping Problematic Rules: Exclude a rule temporarily:
->withSkippedRules([
\RectorLaravel\Rector\MethodCall\RemoveModelPropertyFromFactoriesRector::class,
])
Leverage dev-main for Early Access:
Use the dev-main branch for unreleased rules:
composer require driftingly/rector-laravel:dev-main
Custom Rule Validation: Test new rules in isolation:
vendor/bin/rector test src/Rector/MyCustomRule.php
CI/CD Best Practices:
--fail-on-no-changes to enforce rule application:
vendor/bin/rector process src --fail-on-no-changes
--cache-dir=.rector-cache.Partial Runs: Target specific files/directories:
vendor/bin/rector process app/Http/Controllers --set=LaravelSetList::LARAVEL_STATIC_TO_INJECTION
Post-Rector Checks: Run PHPStan or Psalm after Rector to validate type safety:
vendor/bin/phpstan analyse --level=max
Create Custom Sets:
Combine rules into reusable sets (e.g., app/Rector/CompanySetList.php):
namespace App\Rector;
use Rector\Set\ValueObject\SetList;
final class CompanySetList extends SetList
{
public function getDefinition(): array
{
return [
__DIR__.'/rules/legacy-to-modern.php',
];
}
}
Then use it in rector.php:
->withSets([CompanySetList::class])
Override Default Rules:
Replace or extend existing rules by implementing RectorInterface:
use Rector\Core\Contract\Rector\RectorInterface;
use PhpParser\Node;
final class CustomFacadeRector implements RectorInterface
{
public function refactor(Node $node): ?Node
{
// Custom logic here
}
}
Use Rector in Build Processes:
Integrate with Laravel’s post-update-cmd in composer.json:
"scripts": {
"post-update-cmd": [
"@php artisan optimize",
"@vendor/bin/rector process src --set=LaravelSetList::LARAVEL_CODE_QUALITY --dry-run"
]
}
How can I help you explore Laravel packages today?