はじめに
煩わしい作業ほど自動化させたいというエンジニアの願いは、AIによってある程度叶えられてきていると思います。
ただどうしてもブレが出てしまうので、バージョンアップ作業は素のAIでは心許ない...
そこで今回は、LaravelとPHPのバージョンアップに伴うソース変更も、AIに任せてサクッとやってみたいという願望をRector + Claude Code + Superpowersで叶えられるか、みていきたいと思います!
目標はLaravel 12をLaravel 13にアップデートし、PHP8.4で動いていたコードをPHP8.5で動くようにする、としましょう!
Superpowersってどんなもの?
Superpowersは、Claude CodeをはじめとするAIコーディングツールに構造化されたワークフローを追加するスキルベースの開発フレームワークです。
仕組みの核心は SKILL.md ファイルです。「このタスクにはこのスキルを使って」という指示がSKILLに書かれており、Claude Codeがタスクの内容を判断して自動的に読み込みます。なお、「このviewのここだけ直して」のような単純な修正では発動せず、ある程度複雑なタスクを投げたときにカットインします。
Todoリストなら素のCursor・Claude Codeでも出せますが、Superpowersが違うのはここからです。
- Spec(仕様)を固める — 実装する前に、やりたいことをヒアリングしてSpecドキュメントとして整理。承認が取れるまで実装を開始しない
- Plan(実行計画)を作る — Specを元に、タスクを細分化したPlanをmarkdownファイルとして保存
-
サブエージェントで実行 → 各タスク完了後にPlanとの照合 — タスクが終わるたびに
requesting-code-reviewスキルが自動で起動し、「実装内容がPlanの仕様と一致しているか」をチェック。ズレがあればそこで止まる -
TDD — テストが書けるタスクであれば、専用の
test-driven-developmentスキルがRED→GREEN→REFACTORサイクルを強制する(今回は該当しませんが、真価が発揮されるのは複雑な実装やリファクタリングです!)
「Todoリストを作って順番に実行する」だけなら既存のAIツールでもできますが、Superpowersの本質は各ステップが終わるたびに計画との整合性を自動で確認する点にあります。バージョンアップのような「後で気づいても遅い」作業や、数段階も必要な実装タスクに向いている理由はここです。
Superpowersですが、実は多数のAIツール(Claude Code, Cursor, Codex, Gemini, Github Copilot)で使用可能です!
下記リンクで簡単にインストールできますので、ぜひご活用してみてください!
Rectorとは?
RectorはPHPのPHPやLaravelのバージョンアップの際に利用できる静的解析ベースの自動ツールです。
AIのように「それっぽいコードを生成」するのではなく、定義されたルールセットに従ってコードを機械的に変換します。たとえば「Laravel 13までの変更をすべて適用する」というルールセットを指定すれば、旧記法から新記法へのメソッドや構文の置き換えを実行してくれます。
LaravelLevelSetList::UP_TO_LARAVEL_130 は累積セットです。利用可能な最小セットが UP_TO_LARAVEL_90 のため、UP_TO_LARAVEL_130 にはLaravel 9〜13すべてのバージョンのルールが含まれています。
今回の目標はLaravel 12→13ですが、Rectorは「コードがまだ古い書き方かどうか」を実際に静的解析して判断するため、それ以前のバージョンのルールも該当箇所があれば変更対象になります。過去にRectorを一度も通していないコードベースでは、既存のLaravelより古いバージョンのRectorルールが引っかかることもあります(後述)。
ブレないのが最大の強みですが、あくまで静的な処理なので置換が難しい破壊的な変更や、Factoryの仕様変更など、構造的変更がある場合の対応は手動で行わないといけません!
# インストール
composer require rector/rector --dev
composer require --dev driftingly/rector-laravel
# 初回設定(rector.phpが作成されます)
vendor/bin/rector
Rectorをドライラン(変更なし)で試したい場合のコマンドです:
vendor/bin/rector process --dry-run
今回の作業フロー
- Superpowersとの壁打ちによるアップデートSpecとPlanの作成と、タスク管理(※ここで破壊的変更を明確にして計画を立てましょう)
- PHP 8.5環境でのRector静的解析・コード変換の実行
- 「composer依存パッケージのドライランによるアップデート差分・衝突の確認と実行」からSuperpowersが再度担当
- Laravel公式アップグレードガイドに沿った確認と変更
- PHPUnitテスト・Lint(PHPStan / Pint / PHPCS)・Duskテストの実行
- コードレビュー
- 手動確認(※アップデートのベースができたので、ここからは抜け漏れ・自社ルールに対応しているかの確認ができます✅)
Rectorが静的解析と「一括で置換的なコード変換」の部分を担い、Rectorが及ばない本来手動で反映する箇所を、Claude Superpowersで計画した内容に沿って確認・補完をする形です。
ここで注意するべきことですが、Claude Superpowersの負担がでPHP・Laravelのバージョン差分によってはかなり増えるため、あらかじめSpec作成時点で静的に置換ができない点や破壊的変更を明確にすることで、
自動実行されるPlanに漏れがないようにしましょう。
使用したプロンプト
SuperpowersがインストールされたAI(Claude)に実際に投げたプロンプト:
- Rectorをインストールし、このプロジェクト(laravel 12 and PHP 8.4)をLaravel 13とPHP 8.5にバージョンアップ対応したいので、調査して
- Rector実行後、公式のLaravel13のアップグレードガイドで必要な変更も網羅して(https://laravel.com/docs/13.x/upgrade)
- https://github.com/driftingly/rector-laravel に定義されている、Laravel13までのルールを使用する
- 既にPHP8.5の環境に変更済
- 実行前にRector ドライランで差分確認したい
- 「composerでLaravel12から13に上げること、rectorを実行すること、Laravel13のアップデートマニュアルに沿った修正対応、composerのバージョン依存を踏まえたcomposer衝突解決」も最適な順番で行いたい
- 最後にPHPunit testを実行し、成功したらコードレビューして
プロンプトを受け取ったClaude Superpowersはまず実行に入らず、プロジェクトの状態を把握してから、いくつかの確認を求めてくれました。
現在のLaravelバージョン、PHPバージョン、使用パッケージ、Rectorの有無などを調べたうえで「どの進め方にしますか?」と3択を提示してくれています。今回は A(ドライランで差分を見せた後、各ステップで確認を求めながら進む) を選択しました。
続いて、Superpowersが実行計画をドキュメントとして保存し、セルフレビューを行います。
全9ステップの計画が作成され、「プロンプトの全要件が網羅されているか」を自分でチェックしています。
念のため、こちらからも確認を投げてみました。
すべての要件がどのTaskに対応しているか表形式で整理してくれました。2件の不足点も正直に報告してくれています(phpunit のバージョン指定漏れなど)。
さらに、Task 7(Laravel 13アップグレードガイドの手動対応)について、公式ガイドの全項目が本当に網羅されているかダブルチェックを依頼しました。
プランに記載がなく影響を確認していない項目が他にないか確認をお願いしたところ、最初は漏れて気になっていたphpunitをきちんと列挙してくれました。
ほぼ「対応不要」という結果でしたが、phpunit/phpunit のバージョンの指定漏れをプランに反映してもらってから、実行へ進むことにしました。
今回使用する rector.php の設定はこちらです。
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\PHPUnit\Set\PHPUnitSetList;
use Rector\Set\ValueObject\LevelSetList;
use RectorLaravel\Set\LaravelLevelSetList;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/app',
__DIR__ . '/config',
__DIR__ . '/bootstrap',
__DIR__ . '/routes',
__DIR__ . '/database',
__DIR__ . '/tests',
])
->withSkipPath(__DIR__ . '/bootstrap/cache')
->withSets([
LevelSetList::UP_TO_PHP_85,
LaravelLevelSetList::UP_TO_LARAVEL_130,
PHPUnitSetList::PHPUNIT_120,
]);
withSets にPHP・Laravel・PHPUnitそれぞれのルールセットを指定しております。
このプロジェクトでは使用していた3つのLinterとDuskテストについても追加確認しました。
Task 8 の実行範囲に php artisan dusk のステップが抜けていたため、プランに追記されました。
このように、実行前の「事前確認の繰り返し」がSuperpowersによって自然に組み込まれており、人間が確認できる擬似コンテキスト(Plan)に沿って計画が実行され、完了後「計画通りにタスクが行われたか」が各ステップで確認されます。
すべての確認が終わったところで、実行方式を選択してスタートします!
(※コンテキストの消費・汚染を考慮して1を選択します)
実行の流れ(Task 1〜9)
Task 1:Rectorインストール & 設定ファイル作成
Task 1が完了すると同時に、残りのTodoリストが表示されます。こちらの指摘を反映して routes/ の追加と冗長な withSkipPath(__DIR__ . '/vendor') の削除を行いました。また nunomaduro/larastan が abandoned になっているため larastan/larastan への移行もTask 2で対応することが明示されました。
Task 2:composer.jsonのバージョン更新
サブエージェントがスペックレビュー(実装が計画通りか確認)を挟んでから変更を適用しています。
laravel/framework → ^13.0、php → ^8.5、phpunit/phpunit → ^12.0、larastan/larastan ^3.0 への置き換えなどが完了しました。
Task 3:composer updateドライランで依存衝突を確認
依存衝突なし。主要パッケージがすべて意図通りのバージョンに解決されることを確認できました。サブエージェントが「Symfony v7→v8」などいくつかの懸念を挙げましたが、Laravel 13に追従する正常な変化であることを説明してくれています。確認ポイントで承認してTask 4へ。
Task 4:composer update実行
Laravel Framework 13.7.0 へのアップグレードに成功。さらに composer update 時に発覚した既存バグ(4ファイルのnamespaceに余分な Admin\ が混入)も合わせて修正されました。
Task 5:Rectorドライランで変換差分を確認
app/Models/ 内の6ファイルが変換対象として検出されました。$fillable → #[Fillable]、$hidden → #[Hidden]、$table/$primaryKey → #[Table] などの変換だったので修正しました。
なお、ここで漏れていたrector.phpのLevelSetList::UP_TO_PHP_85 を追加して再度ドライランを実行すると、より多くのPHP8.5に関わる推奨される変更が検出されました。
config/database.php のPDO定数の名前空間修正、クロージャのアロー関数化、型キャストの追加など、PHPバージョンアップに伴う変換が15件追加されています。
気になった変換について掘り下げてみました。
getIdAttribute() が protected function id(): Attribute に変換されるという差分です。機能的に同等ですが、id という名前がEloquent内部でも使われるため動作確認が必要とのこと。
さらにどのRectorルールによる変換かを聞いてみると、
MigrateToSimplifiedAttributeRector は Laravel 9.0で導入された新しいアクセサ記法へ移行するルールで、getXxxAttribute() という Laravel 8以前の書き方がこちらのプロジェクトに残っていたため、 Attribute::make() 形式に書き換えます。
コードベースに古い記法が残っていたところを、UP_TO_LARAVEL_130 の累積セットが拾った形です。12→13のアップデートが目的でも、こうした古い記述まで一緒に検知・修正してくれるのは累積セットならではのメリットです。適用するかどうかの判断材料も丁寧に提示してくれました。
今回は「スキップ推奨」という個人的見解も出してくれましたが、テストで動作確認できるという判断で即適用させることにしました。
Task 6:Rector実行
スペックレビューの指摘($primaryKey の残存)は、Rectorが $table と $primaryKey が揃ったときのみ #[Table] に変換する仕様のためであり、正しい挙動であることが確認されました。
他に、dryrunの際に出力されたPHP8.5の変更も、問題なさそうなものを選んで修正。
Task 7:Laravel 13アップグレードガイドの対応
だいぶタスクとコンテキスト使用しましたが、しっかり事前に計画されていたアップグレードガイドの対応も調査結果に沿って行なってくれます。
Task 6でRectorがスキップした $primaryKey について、「統一した方が良いのでは?」とこちらから指摘したところ、Claudeも「おっしゃる通り。Rectorがスキップしたから正しいというわけではなく、コードの一貫性として統一すべき」と同意しました。
テーブル名と主キーを #[Table] アトリビュートで明示する対応を手動で追加します。
Task 8:Lint / PHPUnit / Duskテスト実行
#[Table] 統一後にPHPUnitを再実行し、255テスト全てPASS。getIdAttribute() → protected function id(): Attribute の変換も問題なしでした。
Lint(PHPStan / Pint / PHPCS)も全クリア。
Task 9:コードレビュー
Superpowersの superpowers:requesting-code-review スキルが起動し、コードレビューが始まります。
指摘事項は以下の2点でした。
-
Important:
AdminPermissionとAdministratorAdminPermissionRelationの#[Table]に冗長なname:が含まれている。Eloquentのデフォルト規約と一致しているため省略を推奨 -
Suggestion:
laravel/breeze ^2.4はLaravel 13では^3.0が正式対応版。ただしBreezeは初期設定時に一度実行したら以降は不要なツールのため、古いバージョンのままでも実害なし
Importantの name: 冗長部分を修正後、最後にもう一度PHPUnit + Duskを実行して全テスト通過を確認しました。
最後、Dusk以外にも実際のWebアプリケーションの挙動も目視で確認して完了です!🏁
SuperpowersとRectorを使用してみた感想
「作業前の認識合わせ」・「チームやプロジェクトの方針にそって修正を実行するかの判断」・「最終確認」はやはり必要になりますが、バージョンアップへの心理的ハードルはかなり減った気がします!
ただ、気をつけないといけない点としては、初期のプランニングで漏れがあるとClaudeはそのプランに忠実に実行してしまいます。
そのため、明示していなかった箇所はそのままスルーされてしまう可能性はあるので、ガチガチなプロンプトを用意するか、プランの内容が十分かどうかの細かい確認はやはり必要ですね...!
とはいえ、Superpowers が事前確認・計画管理・サブエージェント手配・検証・コードレビューを担ってくれて、自然と人間が読める擬似的なコンテキストもSpecやPlanという形で作成されるため、だいぶブレが少なかったと思います。
特に「プロンプトを投げたらいきなり実行するのではなく、まずプロジェクトを調査して計画書を作成する」という動きは、バージョンアップに関わらず、複数の段階で作業をしたい場合にAIの信頼性を大きく上げてくれると感じました!
今後は同じフローでよりバージョン差異が大きい「Laravel 5.x → 8、PHP 7.4 → 8.2」のような規模にも挑戦してみようと思います!
ここまで読んでいただき、ありがとうございました。
それではまた次回お会いしましょう〜
























