php artisan migrate の使い方|オプション一覧とエラー対処まとめ

Artisanコマンドリファレンス

要点(TL;DR)

  • 未適用のマイグレーションを実行してスキーマを最新化するコマンド
  • 最低限の使い方:php artisan migrate
  • よくある罠:
    • 本番は --force 必須(対話なしで実行)
    • 大型DDLはロック・停止時間に注意(特にMySQL)
    • --path相対パス既定。絶対パスなら --realpath

概要

php artisan migrate は、database/migrations 以下(や指定パス)にあるマイグレーションファイルのうち、まだ実行していない分だけをファイル名のタイムスタンプが古い順に実行し、データベースのテーブル構造をコードの定義どおりに更新するArtisanコマンドです。環境差異をなくし、チーム・CI/CD・本番で同じスキーマ履歴を再現するための基礎コマンドで、初回セットアップ時にもテーブルを作成するために実行します。実務ではデプロイ時に --force --no-interaction を併用し、障害時は migrate:rollback で直前バッチを戻します。

構文 / シグネチャ

php artisan migrate [--database=NAME] [--path=PATH] [--realpath] [--schema-path=FILE] \
  [--pretend] [--seed] [--seeder=CLASS] [--step] [--force]

引数(オプション)

オプション必須既定値説明
--databasestringいいえdefaultconfig/database.php の接続名を指定
--pathstringいいえなし実行対象マイグレーションの相対パス(例: database/migrations/subdir
--realpathboolいいえfalse--path絶対パスとして扱う
--schema-pathstringいいえなしスキーマダンプ(schema.sql)の読み込み元
--pretendboolいいえfalse実行せずSQLだけ表示
--seedboolいいえfalseマイグレーション完了後に db:seed も実行
--seederstringいいえDatabaseSeeder併用時に実行するシーダークラスを指定
--stepboolいいえfalse各ファイルを別バッチとして記録(ロールバック単位を細かく)
--forceboolいいえfalse本番など非対話環境で実行を許可

Artisan共通例:-n/--no-interaction(確認をすべてスキップ)、-q/--quiet など。

  • 戻り値:終了コード(成功 0、失敗 非0)
  • 例外/副作用:データベースDDL実行、migrations テーブルへのバッチ記録、--seed 併用時はDML実行

使用例

最小例

# デフォルト接続で未適用分を実行
php artisan migrate

実務例

# 例1:本番デプロイの安全セット(対話なし)
php artisan migrate --force --no-interaction --step

# 例2:特定接続(PostgreSQL)で、サブディレクトリだけ適用
php artisan migrate --database=pgsql --path=database/migrations/tenant

# 例3:挙動確認(SQLのみ出力)
php artisan migrate --pretend

よくある落とし穴・注意

  • 本番で --force 不足:CI/CDやSSH越しの実行は対話不可のため必須。
  • 大型DDLによるロック:MySQLのALTERはテーブルロック・暗黙コミットに注意。オンラインDDL(ALGORITHM=INPLACE など)検討や、段階的移行(カラム追加→並行書き込み→切替→旧カラム削除)を計画。
  • --path の解釈:既定はプロジェクトルートからの相対。絶対パスは --realpath を付与。
  • トランザクション差:PostgreSQLは多くのDDLがトランザクション対応。一方MySQLはDDLで自動コミットされるケースがあり、途中失敗で部分適用になることがある。
  • --step の使いどころ:粒度の細かいロールバックが必要な環境で有効(各ファイルが別バッチに)。

代替・関連APIとの比較

  • migrate:rollback:直近バッチを取り消し。小さく戻したいときは --step=N
  • migrate:refresh全ロールバック→再実行。データは保持されないことに注意。
  • migrate:fresh全テーブルDROP→全実行。開発用の一掃リセット向け。
  • migrate:reset全ロールバックのみ(再実行はしない)。テーブルを空にして止めたいときに使う。
  • migrate:status:適用状況の一覧。トラブル時のファイル漏れ確認に有用。
  • make:migration:定義ファイルを生成。実行は migrate が担当。

選定基準:本番は基本 migrate、障害切り戻しは rollback、ローカル初期化は fresh / refresh

テスト例(Pest)

<?php
use Illuminate\Support\Facades\Schema;

it('migrates successfully', function () {
    $this->artisan('migrate', ['--force' => true])->assertExitCode(0);

    expect(Schema::hasTable('migrations'))->toBeTrue();
});

トラブルシュート(エラー別)

症状/エラー原因対処
SQLSTATE[HY000] [1049] Unknown databaseDB名が存在しない/接続設定誤り.envDB_* を確認、DB作成後に再実行
Base table or view already exists既存テーブルと重複マイグレーションの前提を見直し、条件分岐(Schema::hasTable)や一度 rollback/fresh
Nothing to migrate.すべて適用済み新規ファイル名のタイムスタンプ・配置パスを確認
Class ... already exists / Class not foundクラス名とファイル名の不一致・重複マイグレーションクラス名をユニークに、オートロード再生成(composer dump-autoload
長時間固まる/タイムアウト大型DDLのロック・インデックス作成事前にオンラインDDL・分割適用、メンテナンス時間を確保

追加(artisanカテゴリの要件)

オプション表(要点)

オプション値の型既定値目的
--forceboolfalse非対話環境(本番/CI)で強制実行
--databasestringdefault接続名を切り替え
--pathstringなし特定ディレクトリ/ファイルのみ実行
--realpathboolfalse--path を絶対パスとして扱う
--schema-pathstringなしスキーマダンプの読込
--pretendboolfalse実行SQLの表示のみ
--seedboolfalse実行後にシーディング
--seederstringDatabaseSeeder実行するSeeder指定
--stepboolfalseロールバック単位をファイルごとに

実行環境

  • ローカル:検証や refresh/fresh が中心。
  • CI--force --no-interaction、接続は専用DB。
  • 本番:バックアップ・停止時間の計画、--force 必須、DDLの影響(ロック/レプリケーション)に留意。

副作用

  • スキーマ変更、migrations テーブル更新、--seed 併用時のデータ投入。

終了コード

  • 0: 成功(未適用なしでも成功)
  • >0: 失敗(例外・接続不可・SQLエラー等)

スケジューラ例(参考)

自動実行は推奨度低(デプロイパイプラインでの実行が無難)。検証用/単一ノード検証で使う例:

// app/Console/Kernel.php
protected function schedule(\Illuminate\Console\Scheduling\Schedule $schedule): void
{
    // 毎日3:00に検証用DBへ適用(例)
    $schedule->command('migrate --database=staging --force')
        ->dailyAt('03:00');
}

以上。実務では「デプロイの一部として migrate --force --no-interaction を実行、戻しは rollback --step」を定石にしてください。

よくある質問(FAQ)

Q. php artisan migrate はいつ実行すればいい?
マイグレーションファイルを新規作成・変更した後、そのファイルの内容をデータベースに反映したいタイミングで実行します。make:migration でファイルを生成した直後や、他のメンバーが追加したマイグレーションを git pull で取り込んだ直後、デプロイ時のスキーマ更新などが典型例です。

Q. 実行しても「Nothing to migrate.」としか表示されない
すべてのマイグレーションが適用済みという意味です。新しいファイルが反映されない場合は、ファイル名の日時プレフィックス(2026_01_01_000000_xxx.php)が最新か、--path で意図しないディレクトリを指定していないかを確認してください。

Q. migrate:fresh や migrate:refresh と何が違う?
migrate は未適用分だけを追加実行するのに対し、migrate:fresh は全テーブルをDROPしてから全マイグレーションを再実行、migrate:refresh は全ロールバック後に再実行します。既存データを保ったまま更新したいだけなら migrate を使い、ローカル環境の作り直しには fresh / refresh を使い分けます。

Q. 本番環境でそのまま実行しても大丈夫?
実行前に必ずDBのバックアップを取り、--pretend で実行されるSQLを事前確認してください。対話プロンプトが出ない本番・CI環境では --force が必須です。大型テーブルへのDDLはロックによるサービス影響が出うるため、メンテナンス時間の確保やオンラインDDLの検討も行いましょう。

Q. エラーが出て途中で止まった場合はどうする?
エラーメッセージを本記事の「トラブルシュート」表で照合し、原因を解消したうえで再度 php artisan migrate を実行します。MySQLはDDLが自動コミットされるため部分適用になっていることがあり、migrate:status で現在の適用状況を確認してから対応してください。

参考リンク

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする