見出し画像

RectrorPHPによるFuelPHPからLaravelの移行の自動化

はじめに

弊社のプロダクトはFuelPHPで書かれたものが多いのですが、これらをLaravelに移行するにあたり、可能な部分は機械的に変換することにしました。
今回取り上げるRectorPHPは、PHPコードのリファクタリングやコードの自動修正を行うためのなツールです。本記事では、RectorPHPを導入し、独自のリファクタリングルールを書く方法について紹介します。

RectorPHPのインストール

1. composerのインストール

まずはcomposerをインストールします。composerはPHPの依存関係管理ツールで、RectorPHPのインストールに必要なものです。

curl -sS https://getcomposer.org/installer | php


2. RectorPHPのインストール

次にRectorPHPをインストールします。以下のコマンドを使用して、RectorPHPをプロジェクトに追加します。開発環境でしか使わないのでdevオプションをつけています。

composer require rector/rector:"^0.15.24" --dev

これにより、プロジェクトの composer.json ファイルが更新されます。


3. composer.jsonの更新内容

RectorPHPのインストールにより、composer.json ファイルに以下のような変更が加わります。ここではautoloadの指定も行っています。


{
    "require-dev": {
        "rector/rector": "^0.15.24",
    },
    "autoload-dev": {
        "psr-4": {
            "Utils\\Rector\\": "utils/rector/src",
            "Utils\\Rector\\Tests\\": "utils/rector/tests"
        }
    }
}

これでRectorPHPがプロジェクトに追加されました。


独自ルールの書き方

RectorPHPを使用して独自のリファクタリングルールを書くには、以下の手順に従います。

1. ルールの作成

変換ルールのロジック部分を作成します。今回はInsertRule1.phpという名前で作成しました。

<?php

declare(strict_types=1);

namespace Utils\Rector\Rector\QueryBuilder\Insert;

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

final class InsertRule1 extends AbstractRector
{
    public function getNodeTypes(): array
    {
        return [MethodCall::class];
    }

    public function refactor(Node $executeNode): ?Node
    {
        if (!$this->isName($executeNode->name, 'execute')) {
            return null;
        }

        $setNode = $executeNode->var;
        if (!$setNode instanceof MethodCall || !$this->isName($setNode->name, 'set')) {
            return null;
        }

        $insertNode = $setNode->var;
        if (!$insertNode instanceof StaticCall || !$this->isName($insertNode->name, 'insert')) {
            return null;
        }

        return new MethodCall(
            new StaticCall(
                new Node\Name\FullyQualified('DB'),
                new Node\Identifier('table'),
                $insertNode->args
            ),
            $insertNode->name,
            $setNode->args
        );
    }

    public function getRuleDefinition(): RuleDefinition
    {
        return new RuleDefinition(
            'Change method calls insert',
            [
                new CodeSample(
                    // code before
                    "\DB::insert('table_name')->set(['name' = > 'alice', 'age' => '20'])->execute();",
                    // code after
                    "\DB::table('table_name')->insert(['name' = > 'alice', 'age' => '20']);"
                ),
            ]
        );
    }
}


2. ルールの登録

最後に、作成したRectorクラスをrector.phpファイルに登録します。

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Utils\Rector\Rector\QueryBuilder\Insert\InsertRule1;

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

    $rectorConfig->rules([
        InsertRule1::class,
    ]);
};

InsertRule1::classをルールとして適用しています。
これで独自のリファクタリングルールがRectorPHPに追加されます。

3. ルールの実行

テスト実行をしてみます。パラメータにdry-runをつけるとテストになります。

bash5.2# vendor/bin/rector process ./rector_src/Models/ --config rector.model2.php --dry-run

このように置き換えられた様子を確認できます。

おわりに
本記事では、RectorPHPの導入と独自のリファクタリングルールの作成方法について紹介しました。RectorPHPを使用することで、PHPプロジェクトのコードベースを効率的に改善することができます。是非、ご自身のプロジェクトにも導入してみてください。

▼採用情報はこちら