Rector でのPHP の書き換え

PHP のバージョンアップでは、数百から数千か所の書き換えが必要になることがあります。Rector を使うと、決まったルールに沿って、手作業の漏れなく一括で書き換えられます。
KEY SELECT は、Rector と PHPStan を導入し、ルールを選んで段階的に書き換え、差分をすべてレビューしてから取り込みます。
すべての作業を、セキュリティを意識して進めます。

Rector で書き換えられること

Rector は、PHP のコードを読み、ルールに当てはまる箇所を書き換えるオープンソースのツールです。PHP 5.3 の書き方から、PHP 8.5 と次の 8.6 の書き方まで、バージョンごとのルールを持っています。

削除された関数の置き換え

each()、create_function()、ereg などを、新しいバージョンで動く書き方に置き換えます。

新しい書き方への変換

switch を match に、コンストラクターでのプロパティの宣言に、など、新しいバージョンの書き方に変えます。

非推奨の書き方の修正

暗黙の nullable や、文字列の中の ${var} など、次のバージョンで動かなくなる書き方を直します。

型の追加

確実に分かる型を、引数、戻り値、プロパティに足し、静的解析で不具合を見つけやすくします。

使われていないコードの削除

どこからも使われていないコードや、意味のない処理を取り除き、保守しやすくします。

フレームワークの移行

Symfony、Laravel、CakePHP 3 系以降などのバージョンアップにも、それぞれのルールがあります。

お引き受けできること

ツールに任せきりにせず、エンジニアがルールを選び、すべての差分を確かめます。社内のエンジニアの方と、設定と進め方を共有しながら進められます。

Rector と PHPStan の導入

お使いの PHP とフレームワークに合わせて、Rector と静的解析の PHPStan を導入し、設定します。

ルールの選定

移行先のバージョンと、コードの状態に合わせて、使うルールと、使わないルールを決めます。

段階的な書き換えとレビュー

ルールを少しずつ足し、レビューできる大きさの変更に分けて書き換え、差分をすべて確かめます。

テストでの確認

Rector はコードを動かさないため、結果が変わる変更は、自動テストと画面の操作で確かめます。

CI への組み込み

変更のたびに Rector の検査を動かし、古い書き方が新しく入らないようにします。

移行後の保守

次のバージョンが出たら、同じ仕組みで、新しいルールを足して上げ続けられます。

進め方

Rector の公式のドキュメントが勧めるとおり、一度にすべてのルールを使わず、少しずつ進めます。

  1. 準備

    書き方の決まりのツールと PHPStan を先に入れ、Rector が型を読み取れる状態にします。

  2. PHP のバージョンのルール

    PHP のバージョンごとのルールを 1 つずつ足し、今のバージョンまで書き換えます。

  3. 品質のルール

    型の追加、使われていないコードの削除、コードの品質のルールを、安全なものから順に足します。

  4. レビューとテスト

    変更ごとに差分をレビューし、自動テストで動きが変わらないことを確かめて取り込みます。

  5. CI での確認

    変更のたびに Rector の検査を動かし、書き換えた状態を保ちます。

Rector では直せないこと

Rector はコードを読むだけで、実行しません。そのため、次のものはテストとエンジニアの確認で補います。

結果だけが変わる変更

PHP 8.0 の数値と文字列の比較のように、エラーにならずに結果が変わる変更は見つけられません(バージョンごとの書き方の変化)。

実行時に決まるもの

__get・__call を使った呼び出しや、文字列で指定したクラスなど、読むだけでは型が分からないものは書き換えられません。

書き方の整形

書き換えた箇所の見た目は整えません。PHP-CS-Fixer などで整えます。

テンプレート

Twig、Blade などのテンプレートのファイルは対象外です。

技術者の方へ

Rector 2.7.0 (2026 年 10 月 6 日) の設定と使い方です。Rector 自体を動かすには PHP 7.4 以上が必要です (Composer のパッケージの条件。公式のドキュメントの一部には 7.2 以上と書かれています)。

入れ方と動かし方

# 開発用のパッケージとして入れる(初めて動かすと、rector.php を作るかを尋ねる)
composer require rector/rector --dev

# 書き換えずに、変わる箇所の差分だけを表示する
vendor/bin/rector process --dry-run

# 書き換える
vendor/bin/rector process

# CI: 書き換えるべき箇所が残っていると、終了コード 1 で失敗する
vendor/bin/rector process --dry-run --no-progress-bar --output-format=github

設定の例 (rector.php)

<?php

use Rector\Config\RectorConfig;

return RectorConfig::configure()
    ->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
    // 引数を省くと、composer.json の PHP のバージョンまでのルールを使う
    ->withPhpSets()
    // 型の追加、使われていないコードの削除、コードの品質のルールを、安全なものから N 個まで
    ->withTypeCoverageLevel(0)
    ->withDeadCodeLevel(0)
    ->withCodeQualityLevel(0);
  • withPhpSets() は、composer.json の require.php の下限 (なければ config.platform.php) のバージョンまでの、すべてのルールを使います。PHP 7.4 で動かす場合は、名前付き引数を使わない withPhpLevel() を使います
  • 最初は withPhpLevel(0) から始めて数字を 1 つずつ上げ、今のバージョンまでのルールがすべて入ったら withPhpSets() に切り替えます
  • PHP 8.1 で非推奨になった「組み込みの関数に null を渡す」書き方を直す NullToStrictStringFuncCallArgRector と、#[\ReturnTypeWillChange] を付けるルールは、PHP のバージョンのセットに含まれていません。必要な場合は withRules() で足します

PHP のバージョンごとのルールの例

セットルールの例書き換えの内容
PHP 7.0Php4ConstructorRector、EregToPregMatchRectorPHP 4 の形のコンストラクターを __construct に、ereg を preg に
PHP 7.2CreateFunctionToAnonymousFunctionRector、ListEachRectorcreate_function() を無名関数に、each() を置き換え
PHP 7.4CurlyToSquareBracketArrayStringRector$str{0} を $str[0] に
PHP 8.0ChangeSwitchToMatchRector、StrContainsRectorswitch を match に、strpos() !== false を str_contains() に
PHP 8.2VariableInStringInterpolationFixerRector文字列の中の ${var} を {$var} に
PHP 8.4ExplicitNullableParamTypeRector暗黙の nullable を ?string の形に
PHP 8.5ShellExecFunctionCallOverBackticksRectorバッククォートを shell_exec() に

フレームワークのルール

対象パッケージ開発元
Symfony、Doctrine、PHPUnitrector-symfony、rector-doctrine、rector-phpunitRector の開発元。Rector に含まれる
Laraveldriftingly/rector-laravelLaravel のコミュニティ
CakePHP 3 系以降cakephp/upgradeCakePHP の開発元。3 系から 4 系、4 系から 5 系に対応。PHP 8.2 以上が必要

CakePHP 2 系は、新しいフレームワークへ移す前に、PHP 8 系で動かす方法もあります (CakePHP 2 系の延命と移行)。

ご相談・お問い合わせ

内容が固まっていない段階からご相談いただけます。各分野のプロフェッショナルがご対応いたします。ご相談・お見積もりは無料です。