# Rector Laravel - Automated Laravel Refactoring Rules Rector Laravel is a community-driven extension for the Rector PHP automated refactoring tool, providing over 106 rules specifically designed for Laravel applications. It enables automatic code upgrades between Laravel framework versions (5.0 through 13.0), code quality improvements, and migration to modern Laravel patterns. The package supports first-party Laravel packages including Cashier, Livewire, and Faker. The library works by analyzing PHP code using abstract syntax trees (AST) and applying transformation rules to automatically refactor deprecated patterns, upgrade legacy code, and enforce best practices. It integrates with Rector's configuration system and can automatically detect your Laravel version from `composer.json` to apply the appropriate upgrade rules. ## Installation Install the package as a dev dependency. ```bash composer require --dev driftingly/rector-laravel ``` ## Automatic Laravel Version Detection Configure Rector to automatically detect and apply rules based on your Laravel version from composer.json. ```php withPaths([ __DIR__ . '/app', __DIR__ . '/config', __DIR__ . '/database', __DIR__ . '/routes', __DIR__ . '/tests', ]) ->withSetProviders(LaravelSetProvider::class) ->withComposerBased(laravel: true); ``` ## Manual Laravel Version Configuration Manually specify the target Laravel version using level sets that include all rules for lower versions. ```php withPaths([ __DIR__ . '/app', ]) ->withSets([ LaravelLevelSetList::UP_TO_LARAVEL_130, ]); // Available level sets: // LaravelLevelSetList::UP_TO_LARAVEL_51 through UP_TO_LARAVEL_130 ``` ## Specific Version Upgrade Rules Apply rules for a specific Laravel version upgrade only (e.g., upgrading from Laravel 12 to Laravel 13). ```php withPaths([ __DIR__ . '/app', ]) ->withSets([ LaravelSetList::LARAVEL_130, ]); // Available version sets: // LaravelSetList::LARAVEL_50 through LARAVEL_130 ``` ## Code Quality Set Apply Laravel-specific code quality improvements including modern helper functions, facade usage, and best practices. ```php withPaths([__DIR__ . '/app']) ->withSets([ LaravelSetList::LARAVEL_CODE_QUALITY, ]); // Transforms code like: // Before: $app->environment() === 'local' // After: $app->isLocal() // Before: now()->startOfDay() // After: today() // Before: redirect()->back()->with('error', 'msg') // After: back()->with('error', 'msg') // Before: sleep(5) // After: \Illuminate\Support\Sleep::sleep(5) ``` ## Collection Improvements Set Simplify and improve Laravel Collection usage with more readable method calls. ```php withPaths([__DIR__ . '/app']) ->withSets([ LaravelSetList::LARAVEL_COLLECTION, ]); // Transforms code like: // Before: $collection->filter(fn ($n) => ! is_null($n)) // After: $collection->reject(fn ($n) => is_null($n)) // Before: ! $collection->contains($item) // After: $collection->doesntContain($item) // Before: $collection->average() // After: $collection->avg() ``` ## If Helpers Set Convert if statements with abort, report, and throw to Laravel helper functions. ```php withPaths([__DIR__ . '/app']) ->withSets([ LaravelSetList::LARAVEL_IF_HELPERS, ]); // Transforms code like: // Before: // if ($condition) { // abort(404); // } // After: // abort_if($condition, 404); // Before: // if (!$condition) { // throw new Exception(); // } // After: // throw_unless($condition, new Exception()); // Before: // if ($error) { // report(new Exception()); // } // After: // report_if($error, new Exception()); ``` ## Facade to Dependency Injection Set Replace Laravel Facade static calls with proper dependency injection. ```php withPaths([__DIR__ . '/app']) ->withSets([ LaravelSetList::LARAVEL_STATIC_TO_INJECTION, ]); // Transforms code like: // Before: // class SomeController { // public function action() { // $template = view('template.blade'); // } // } // After: // class SomeController { // private \Illuminate\Contracts\View\Factory $viewFactory; // // public function __construct(\Illuminate\Contracts\View\Factory $viewFactory) { // $this->viewFactory = $viewFactory; // } // // public function action() { // $template = $this->viewFactory->make('template.blade'); // } // } ``` ## Factory Improvements Set Modernize Eloquent Factory usage with better IDE support and type safety. ```php withPaths([__DIR__ . '/database/factories']) ->withSets([ LaravelSetList::LARAVEL_FACTORIES, ]); // Transforms code like: // Before: // class UserFactory extends Factory { // protected $model = \App\Models\User::class; // } // After: // /** // * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User> // */ // class UserFactory extends Factory { // protected $model = \App\Models\User::class; // } // Before: $this->faker->name // After: fake()->name ``` ## Legacy Factories to Classes Set Migrate Laravel 7 and earlier closure-based factories to modern class-based factories. ```php withPaths([__DIR__ . '/database/factories']) ->withSets([ LaravelSetList::LARAVEL_LEGACY_FACTORIES_TO_CLASSES, ]); // Transforms code like: // Before (database/factories/UserFactory.php): // $factory->define(App\User::class, function (Faker $faker) { // return [ // 'name' => $faker->name, // 'email' => $faker->unique()->safeEmail, // ]; // }); // After: // class UserFactory extends \Illuminate\Database\Eloquent\Factories\Factory // { // protected $model = App\User::class; // // public function definition() // { // return [ // 'name' => $this->faker->name, // 'email' => $this->faker->unique()->safeEmail, // ]; // } // } ``` ## Eloquent Magic Methods to Query Builder Set Convert Eloquent magic method calls to explicit Query Builder calls for better IDE support. ```php withPaths([__DIR__ . '/app']) ->withSets([ LaravelSetList::LARAVEL_ELOQUENT_MAGIC_METHOD_TO_QUERY_BUILDER, ]); // Transforms code like: // Before: User::first() // After: User::query()->first() // Before: User::where('active', true)->get() // After: User::query()->where('active', true)->get() ``` ## Testing Improvements Set Improve Laravel test code with modern assertions and methods. ```php withPaths([__DIR__ . '/tests']) ->withSets([ LaravelSetList::LARAVEL_TESTING, ]); // Transforms code like: // Before: $response->assertStatus(200) // After: $response->assertOk() // Before: $response->assertStatus(404) // After: $response->assertNotFound() // Before: Carbon::setTestNow('2024-08-11') // After: $this->travelTo('2024-08-11') // Before: $this->json("POST", "/api/users", $data) // After: $this->postJson("/api/users", $data) // Before: $response->assertSee("