3.

Laravel マイグレーションファイルの作成 (make:migration / Schema::create / down 実装)

編集
この記事の要点
  • php artisan make:migration create_users_tabledatabase/migrations/ 配下に雛形生成
  • 雛形には up() / down() の 2 メソッド。up は前進、down は巻き戻し
  • カラム定義は Schema::create 内で $table->string(...) 等の流暢な API
  • 主要カラム: id / string / integer / boolean / timestamp / foreignId / json
  • 実行: php artisan migrate、巻き戻し: migrate:rollback、初期化: migrate:fresh --seed
  • 本番では --force 必須 + バックアップ + ダウンタイム対策 (zero-downtime migration)

マイグレーションとは

Laravel のマイグレーションはDB スキーマの変更を PHP コードで管理する仕組みです。テーブル作成・カラム追加・インデックス追加などをコード化し、Git で履歴管理してチーム全員の DB を同期できます。

1. ファイル生成

# テーブル新規作成 (規約名: create_*_table)
php artisan make:migration create_users_table

# 既存テーブルへの変更 (規約名: add_/change_/drop_*_to_*_table)
php artisan make:migration add_avatar_to_users_table --table=users

# 任意ファイル名
php artisan make:migration create_articles_table --create=articles

生成されるファイルは database/migrations/2026_06_11_120000_create_users_table.php のようにタイムスタンプ + 名前形式です。実行順はファイル名昇順。

2. 雛形の中身

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();                       // BIGINT UNSIGNED AUTO_INCREMENT PK
            $table->string('name');             // VARCHAR(255)
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();            // VARCHAR(100) nullable
            $table->timestamps();               // created_at / updated_at
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};

3. よく使うカラム型

メソッドSQL 相当
id()bigIncrements('id') の別名
string('name', 100)VARCHAR(100)
text('body')TEXT
longText('content')LONGTEXT
integer('count')INT
bigInteger('amount')BIGINT
decimal('price', 8, 2)DECIMAL(8,2)
boolean('is_active')TINYINT(1)
date('birthday')DATE
dateTime('published_at')DATETIME
timestamp('expires_at')TIMESTAMP
timestamps()created_at / updated_at
softDeletes()deleted_at NULL
json('meta')JSON
uuid('uuid')CHAR(36)
enum('role', ['admin','user'])ENUM(...)
foreignId('user_id')BIGINT UNSIGNED (FK 用)

4. 修飾子 (Modifier)

$table->string('email')->unique();              // ユニーク
$table->string('nickname')->nullable();         // NULL 可
$table->integer('count')->default(0);           // デフォルト
$table->integer('age')->unsigned();             // UNSIGNED
$table->string('slug')->index();                // インデックス
$table->string('email')->comment('ログイン用');    // コメント
$table->string('name')->after('id');            // 列順 (MySQL のみ)
$table->string('status')->charset('utf8mb4');   // 文字セット
$table->timestamp('created_at')->useCurrent();  // DEFAULT CURRENT_TIMESTAMP
$table->timestamp('updated_at')->useCurrentOnUpdate();

5. 外部キー (foreignId)

Schema::create('articles', function (Blueprint $table) {
    $table->id();

    // 推奨: foreignId + constrained
    $table->foreignId('user_id')
          ->constrained()              // users テーブルを参照
          ->cascadeOnDelete()          // 親削除で子も削除
          ->cascadeOnUpdate();

    // 任意のテーブル/カラムを指定
    $table->foreignId('category_id')
          ->constrained('categories', 'id')
          ->nullOnDelete();

    $table->string('title');
    $table->text('body');
    $table->timestamps();
});

6. 既存テーブルの変更

// up: 追加
Schema::table('users', function (Blueprint $table) {
    $table->string('avatar')->nullable()->after('name');
    $table->index('email');
});

// down: 元に戻す
public function down(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropIndex(['email']);
        $table->dropColumn('avatar');
    });
}

// カラム型の変更 (doctrine/dbal が必要)
// composer require doctrine/dbal
Schema::table('users', function (Blueprint $table) {
    $table->string('name', 100)->change();
});

// カラム名変更
Schema::table('users', function (Blueprint $table) {
    $table->renameColumn('name', 'full_name');
});

7. 実行・巻き戻し

# 未適用ぶんを順に実行
php artisan migrate

# 直近 1 バッチを巻き戻し
php artisan migrate:rollback

# 直近 5 つを巻き戻し
php artisan migrate:rollback --step=5

# 全部巻き戻し
php artisan migrate:reset

# 全部巻き戻し → 全部実行
php artisan migrate:refresh

# DROP → 全部実行 (★ データ全消し)
php artisan migrate:fresh
php artisan migrate:fresh --seed     # シードまで流す

# 状態確認
php artisan migrate:status

# 本番 (確認プロンプトをスキップ)
php artisan migrate --force

8. down() メソッドを書く理由

down() を真面目に書くと migrate:rollback で安全に戻せます。テスト環境やローカルで「やっぱりやめた」が即できるのがメリット。本番では使わない方針 (前進専用) のチームもあります。

public function up(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('phone')->nullable();
    });
}

public function down(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('phone');
    });
}

9. 本番運用での注意

  • 必ず事前バックアップを取る (mysqldump / pg_dump)
  • 大きなテーブルへの ALTER はテーブルロックになる場合あり → 深夜帯 or pt-online-schema-change
  • カラム削除や型変更は後方互換を 2 リリースに分割: ① 新カラム追加 → ② コード移行 → ③ 旧カラム削除
  • migrate:fresh本番で絶対に流さない (.env で APP_ENV=production なら警告)
  • 本番のテーブル設計は1 マイグレーション = 1 変更を推奨。差し戻しが楽

10. シーダとの組合せ

# シーダ作成
php artisan make:seeder UserSeeder

# マイグレーション + シーダを一気に
php artisan migrate --seed
php artisan migrate:fresh --seed

FAQ

Q: 既に流したマイグレーションをやり直したい
A: migrate:rollback で巻き戻してから編集して再 migrate。本番では使えないので、本番修正用の追加マイグレーションを書きます。

Q: 1 PR で 10 個のマイグレーションが溜まる
A: そのままで OK。タイムスタンプ順に流れるので衝突しません。ただしレビューしやすいよう機能ごとに PR を分けるのが推奨。

Q: schema dump で短縮したい
A: php artisan schema:dump --prune で過去マイグレーションを 1 つの SQL に集約。新規環境のセットアップが高速化します。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 新規プロジェクトの作成
  2. サーバーの起動
  3. マイグレーションファイルの作成
  4. マイグレーションの実行(migrate)
  5. モデルの作成
  6. 全ルートを確認
  7. Laravelのバージョンの確認方法

最近更新/作成されたページ