はじめに

数年以上、数世代以上前のLaravel プロジェクトを新しいLaravel 12へ移行する際、段階的なアップグレードは非常に手間がかかります。プロジェクトの規模が小規模〜中規模であれば、新規プロジェクトを作成して移行する方法が効率的です。

Claude codeなどを利用することで、両方の構造の違いを分析して自動でファイルを作成することも可能です。

移行の判断基準

新規作成がおすすめのケース

  • モデル数が10個以下
  • コントローラーが10個以下
  • カスタムパッケージへの依存が少ない
  • テストカバレッジが低い

段階的アップグレードが必要なケース

  • 大規模プロジェクト(モデル50個以上など)
  • 複雑なカスタムパッケージを多用
  • テストカバレッジが高く、テストを維持したい

Docker環境の構築

PHP 8.3 + MySQL 8.0 + NginxのDocker環境を構築します。

docker-compose.yml

services:
  app:
    build:
      context: .
      dockerfile: docker/php/Dockerfile
    volumes:
      - .:/var/www/html
    depends_on:
      - mysql

  nginx:
    image: nginx:alpine
    ports:
      - "8082:80"
    volumes:
      - .:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app

  mysql:
    image: mysql:8.0
    platform: linux/amd64  # M1/M2 Mac用
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - "33062:3306"

volumes:
  mysql-data:

docker/php/Dockerfile

FROM php:8.3-fpm

RUN apt-get update && apt-get install -y \
    git curl libpng-dev libonig-dev libxml2-dev libzip-dev zip unzip \
    && docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

Laravel 12のインストール

# コンテナ内でLaravelをインストール
docker exec app composer create-project laravel/laravel /tmp/laravel-tmp
docker exec app bash -c "cp -r /tmp/laravel-tmp/. /var/www/html/"

主な変更点

1. モデルの配置場所

Laravel 旧バージョンではappディレクトリ直下でしたが、Laravel 8以降はapp/Modelsに配置します。

// 旧: app/User.php
namespace App;

// 新: app/Models/User.php
namespace App\Models;

2. マイグレーションの書き方

// 旧: クラス形式
class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create(users, function (Blueprint $table) {
            $table->increments(id);
        });
    }
}

// 新: 無名クラス形式
return new class extends Migration
{
    public function up(): void
    {
        Schema::create(users, function (Blueprint $table) {
            $table->id();  // bigIncrements の省略形
        });
    }
};

3. ルートの書き方

// 旧: 文字列形式
Route::get(/users, UserController@index);

// 新: 配列形式(推奨)
use App\Http\Controllers\UserController;
Route::get(/users, [UserController::class, index]);

4. リレーションの型指定

// 旧
public function posts()
{
    return $this->hasMany(AppPost);
}

// 新
use Illuminate\Database\Eloquent\Relations\HasMany;

public function posts(): HasMany
{
    return $this->hasMany(Post::class);
}

データ移行

本番環境のデータベースをダンプして、Docker環境にインポートします。

# 本番からダンプ
mysqldump -u user -p database_name > backup.sql

# Dockerにインポート
docker exec -i mysql-container mysql -uroot -proot database_name < backup.sql

注意点

  • 外部キー制約の型: 旧版がint(unsigned)で新版がbigint(unsigned)の場合、インポート時にエラーが発生します。SQLファイルを直接インポートするか、マイグレーションの型を合わせる必要があります。
  • 非推奨パッケージ: fideloper/proxyやlaravelcollective/htmlなど、廃止・統合されたパッケージがあります。
  • PHP 8の構文: コンストラクタプロパティプロモーション、名前付き引数、match式などが使えるようになります。

まとめ

小〜中規模プロジェクトであれば、段階的アップグレードより新規作成+移行の方が効率的です。Docker環境を用意し、モデル・マイグレーション・コントローラー・ビューを順次移行していくことで、クリーンな状態でLaravel 12の恩恵を受けられます。

カスタマイズに関するお問い合わせはこちら