💬

Rectorを使って地獄のLaravelアップグレード作業をEASYにしよう[Laravel7→11]

2025/03/06に公開

はじめに

あるプロジェクトで、PHP・Laravelのアップグレードを行うことになりました。
バージョンを確認したところ、Laravel7でした。がんばって11まで上げていかなくてはなりません。
アップグレード作業は未経験であり、ましてやLaravel7→11と八艘飛びな変更であるため、「間違いなくやらかすぞ!?」と戦々恐々でした。

はてさて、どっから手を付けたらいいものか。ミスを減らしながら、楽にできる方法は無いかと探していたところ、Rectorに出会いました。

Rectorがなければ、私は爆発していました。
Rectoreへの感謝を込めて、Rector推し記事を書いた次第です。

この記事を読んで欲しい人

  • PHP・Laravelのアップグレードしたい人!
  • アップグレード作業が不慣れ・未経験の人

Rector、Rector-laravelとは

公式がこちら
https://github.com/rectorphp/rector/tree/main

RectorはPHPコードを即座にアップグレード、リファクタリングします。PHP、Laravelだけでなく、Symfony、PHPUnit、Doctrineなどをサポートしています。
更に、Rectorの拡張機能として、Laravelコミュニティが開発した"Rector-laravel"が提供されています。本記事ではRector&Rector-laravelにより、PHPとLaravelのバージョンアップのやりかたを記述します。

Rectorをインストールし、rector.phpを以下のように書き換え、実行するだけで、非推奨になった記述法などを検出し、アップグレードに対応したコードに一気に書き換えてくれます!素敵!

↓これでLaravel11の記法に変更してくれる。素敵!

<?php declare(strict_types=1);

use Rector\Config\RectorConfig;
use RectorLaravel\Set\LaravelLevelSetList;

return RectorConfig::configure()
    ->withSets([
        LaravelLevelSetList::UP_TO_LARAVEL_110,
    ]);

Rector、Rector-laravelの導入方法

composer require rector/rector --dev
composer require driftingly/rector-laravel --dev
を実行します。

rector.phpの書き換え

rector.phpのconfigを書き換え、アップグレードしたいPHPやLaravelのバージョンに調整します。

<?php declare(strict_types=1);

use Rector\Config\RectorConfig;
use RectorLaravel\Set\LaravelLevelSetList;

return RectorConfig::configure()
    ->withSets([
        LevelSetList::UP_TO_PHP_84,  // PHP 8.4の機能を有効化
        LaravelLevelSetList::UP_TO_LARAVEL_110,
    ]);

LevelSetList::UP_TO_PHP_80にすると、PHP8.0に対応したコード修正ができます
Laravelは7→8→9→10→11と段階的に上げていく必要がありますが、LaravelLevelSetList::UP_TO_LARAVEL_80と記述すればLaravel8に対応したコード修正ができるので、段階的に上げていくのも簡単です。

実行!

いよいよ、Rectorを実行してコードを修正しましょう。

ドライランを行うと、変更点をターミナルで明記してくれます。
vendor/bin/rector process --dry-run

実際にコードを書き換える際はドライランオプションを消して実行すればOKです!
vendor/bin/rector process

これでコード修正ができました!!

おわりに

折角なので、実際に使用したrector.phpファイルの中身をお見せします。

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use RectorLaravel\Set\LaravelSetList;
use Rector\Set\ValueObject\LevelSetList;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector;
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
use Rector\DeadCode\Rector\ClassMethod\RemoveUselessParamTagRector;
use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
use Rector\PHPUnit\Set\PHPUnitSetList;


return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/app',
        __DIR__ . '/config',
        __DIR__ . '/database',
        __DIR__ . '/routes',
        __DIR__ . '/routes/web.php',
        __DIR__ . '/tests',
    ]);

    // Laravel 11への移行に必要なルールセット
    $rectorConfig->sets([
        LaravelSetList::LARAVEL_110,  // Laravel 11.0への移行ルール
        LaravelSetList::LARAVEL_CODE_QUALITY,
        LevelSetList::UP_TO_PHP_84,  // PHP 8.4の機能を有効化
        PHPUnitSetList::PHPUNIT_100,
    ]);

    // PHP 8.4の機能を活用するためのルール
    $rectorConfig->rule(TypedPropertyFromStrictConstructorRector::class);
    $rectorConfig->rule(ClassPropertyAssignToConstructorPromotionRector::class);
    $rectorConfig->rule(RemoveUselessParamTagRector::class);
    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);

    // インポート設定
    $rectorConfig->importNames();
    $rectorConfig->importShortClasses(false);

    // スキップ設定
    $rectorConfig->skip([
        __DIR__ . '/vendor',
        __DIR__ . '/bootstrap/cache',
        __DIR__ . '/storage',
        __DIR__ . '/.phpunit.cache',
        __DIR__ . '/node_modules',
    ]);
};

Discussion