Laravel 5.6 データベース:マイグレーション

イントロダクション

マイグレーションとはデータベースのバージョンコントロールのような機能です。アプリケーションデータベースのスキーマの更新をチームで簡単に共有できるようにしてくれます。マイグレーションは基本的にLaravelのスキーマビルダとペアで使い、アプリケーションのデータベーススキーマの作成を楽にしてくれます。もしあなたが今まで、チームメイトに彼らのローカルデータベーススキーマに手作業でカラムを追加するよう依頼したことがあるなら、データベースマイグレーションは、そうした問題を解決してくれます。

LaravelのSchemaファサードは、テーブルの作成や操作をサポートしてるデータベースシステム全部に対しサポートします。

マイグレーション生成

make:migration Artisanコマンドを使いマイグレーションを生成できます。

php artisan make:migration create_users_table

マイグレーションはdatabase/migrationsフォルダに設置されます。マイグレーションの実行順をフレームワークに知らせるため、名前にタイムスタンプが含まれています。

--table--createオプションも、テーブル名とマイグレーションで新しいテーブルを生成するかを指定するために使用できます。これらのオプションは生成するマイグレーションスタブの中へ指定したテーブルを予め埋め込みます。

php artisan make:migration create_users_table --create=users

php artisan make:migration add_votes_to_users_table --table=users

マイグレーションの生成出力先のパスを指定したい場合は、make:migrateコマンドの実行時に--pathオプションを付けてください。パスはアプリケーションのベースパスからの相対位置です。

マイグレーション構造

マイグレーションはupdownの2メソッドを含んでいます。upメソッドは新しいテーブル、カラム、インデックスをデータベースに追加するために使用し、一方のdownメソッドはupメソッドが行った操作を元に戻します。

両方のメソッドでは、記述的にテーブルを作成したり、変更したりできるLaravelスキーマビルダが使えます。Schemaビルダで使用できる全メソッドは、このドキュメント後半で確認してください。例としてflightsテーブルを作成するマイグレーションを見てください。

<?php

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

class CreateFlightsTable extends Migration
{
    /**
     * マイグレーション実行
     *
     * @return void
     */
    public function up()
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('airline');
            $table->timestamps();
        });
    }

    /**
     * マイグレーションを元に戻す
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('flights');
    }
}

マイグレーション実行

アプリケーションで用意したマイグレーションを全部実行するには、migrate Artisanコマンドを使用します。

php artisan migrate

Note: Homestead仮想マシンを使用している場合、このコマンドは仮想マシン内で実行してください。

実働環境でのマイグレーション強制

いくつかのマイグレーション操作は破壊的です。つまりデーターを失う可能性があります。実働環境(production)のデータベースに対し、こうしたコマンドが実行されることから保護するために、コマンド実行前に確認のプロンプトが表示されます。コマンド実行時のプロンプトを出さないためには、--forceフラグを指定してください。

php artisan migrate --force

ロールバック

最後のマイグレーション操作をロールバックしたい場合は、rollbackコマンドを使います。このロールバックは、最後に「一度に」実行したマイグレーションをまとめて元に戻します。

php artisan migrate:rollback

rollbackコマンドにstepオプションを付けると、巻き戻す数を限定できます。たとえば、次のコマンドは最後の5マイグレーションをロールバックします。

php artisan migrate:rollback --step=5

migrate:resetコマンドはアプリケーション全部のマイグレーションをロールバックします。

php artisan migrate:reset

rollbackとmigrateの1コマンド実行

migrate:refreshコマンドは全部のデータベースマイグレーションを最初にロールバックし、それからmigrateコマンドを実行します。このコマンドはデータベース全体を作り直すために便利です。

php artisan migrate:refresh

// データベースをリフレッシュし、全データベースシードを実行
php artisan migrate:refresh --seed

refreshコマンドにstepオプションを付けると、巻き戻してからマイグレーションを再実行する数を限定できます。たとえば、次のコマンドは最後の5マイグレーションをロールバック後にマイグレートします。

php artisan migrate:refresh --step=5

全テーブル削除後のマイグレーション

migrate:freshコマンドは、データベースから全テーブルをドロップします。次に、migrateコマンドを実行してください。

php artisan migrate:fresh

php artisan migrate:fresh --seed

テーブル

テーブル作成

新しいデータベーステーブルを作成するには、Schemaファサードのcreateメソッドを使用します。createメソッドは引数を2つ取ります。最初はテーブルの名前で、2つ目は新しいテーブルを定義するために使用するBlueprintオブジェクトを受け取る「クロージャ」です。

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

もちろんテーブル作成時には、テーブルのカラムを定義するためにスキーマビルダのカラムメソッドをどれでも利用できます。

テーブル/カラムの存在チェック

hasTablehasColumnメソッドを使えば、テーブルやカラムの存在を簡単にチェックできます。

if (Schema::hasTable('users')) {
    //
}

if (Schema::hasColumn('users', 'email')) {
    //
}

データベース接続とテーブル操作

デフォルト接続以外のデータベース接続でスキーマ操作を行いたい場合は、connectionメソッドを使ってください。

Schema::connection('foo')->create('users', function (Blueprint $table) {
    $table->increments('id');
});

テーブルのオプションを定義するため、以下のコマンドがスキーマビルダで使用できます。

コマンド 説明
$table->engine = 'InnoDB'; テーブルストレージエンジンの指定(MySQL)
$table->charset = 'utf8'; テーブルのデフォルトキャラクターセットの指定(MySQL)
$table->collation = 'utf8_unicode_ci'; テーブルのデフォルトコロケーションの指定(MySQL)
$table->temporary(); 一時テーブルの作成(SQL Server以外)

テーブルリネーム/削除

既存のデータベーステーブルの名前を変えたい場合は、renameメソッドを使います。

Schema::rename($from, $to);

存在するテーブルを削除する場合は、dropdropIfExistsメソッドを使います。

Schema::drop('users');

Schema::dropIfExists('users');

外部キーを持つテーブルのリネーム

テーブルのリネームを行う前に、Laravelの規約に基づいた名前の代わりに、マイグレーションファイル中で独自の名前付けた外部キー制約が存在していないか確認してください。そうしないと、外部キー制約名は古いテーブル名を参照してしまいます。

カラム

カラム作成

存在するテーブルを更新するには、Schemaファサードのtableメソッドを使います。createメソッドと同様に、tableメソッドは2つの引数を取ります。テーブルの名前と、テーブルにカラムを追加するために使用するBlueprintインスタンスを受け取る「クロージャ」です。

Schema::table('users', function (Blueprint $table) {
    $table->string('email');
});

使用できるカラムタイプ

当然ながらスキーマビルダは、テーブルを構築する時に使用する様々なカラムタイプを持っています。

コマンド 説明
$table->bigIncrements('id'); 符号なしBIGINTを使用した自動増分ID(主キー)
$table->bigInteger('votes'); BIGINTカラム
$table->binary('data'); BLOBカラム
$table->boolean('confirmed'); BOOLEANカラム
$table->char('name', 100); オプションの文字長を指定するCHARカラム
$table->date('created_at'); DATEカラム
$table->dateTime('created_at'); DATETIMEカラム
$table->dateTimeTz('created_at'); タイムゾーン付きDATETIMEカラム
$table->decimal('amount', 8, 2); 有効(全体桁数)/小数点以下桁数指定のDECIMALカラム
$table->double('amount', 8, 2); 有効(全体桁数)/小数点以下桁数指定のDOUBLEカラム
$table->enum('level', ['easy', 'hard']); ENUMカラム
$table->float('amount', 8, 2); 有効(全体桁数)/小数点以下桁数指定のFLOATカラム
$table->geometry('positions'); GEOMETRYカラム
$table->geometryCollection('positions'); GEOMETRYCOLLECTIONカラム
$table->increments('id'); 符号なしINTを使用した自動増分ID(主キー)
$table->integer('votes'); INTEGERカラム
$table->ipAddress('visitor'); IPアドレスカラム
$table->json('options'); JSONフィールド
$table->jsonb('options'); JSONBフィールド
$table->lineString('positions'); LINESTRINGカラム
$table->longText('description'); LONGTEXTカラム
$table->macAddress('device'); MACアドレスカラム
$table->mediumIncrements('id'); 符号なしMEDIUMINTを使用した自動増分ID(主キー)
$table->mediumInteger('votes'); MEDIUMINTカラム
$table->mediumText('description'); MEDIUMTEXTカラム
$table->morphs('taggable'); 符号なしBIGINTのtaggable_idと文字列のtaggable_typeを追加
$table->multiLineString('positions'); MULTILINESTRINGカラム
$table->multiPoint('positions'); MULTIPOINTカラム
$table->multiPolygon('positions'); MULTIPOLYGONカラム
$table->nullableMorphs('taggable'); NULL値可能なmorphs()カラム
$table->nullableTimestamps(); timestamps()メソッドの別名
$table->point('position'); POINTカラム
$table->polygon('positions'); POLYGONカラム
$table->rememberToken(); VARCHAR(100)でNULL値可能なremember_tokenを追加
$table->smallIncrements('id'); 符号なしSMALLINTを使用した自動増分ID(主キー)
$table->smallInteger('votes'); SMALLINTカラム
$table->softDeletes(); ソフトデリートのためにNULL値可能なdeleted_at TIMESTAMPカラム追加
$table->softDeletesTz(); ソフトデリートのためにNULL値可能なdeleted_atタイムゾーン付きTIMESTAMPカラム追加
$table->string('name', 100); オプションの文字長を指定したVARCHARカラム
$table->text('description'); TEXTカラム
$table->time('sunrise'); TIMEカラム
$table->timeTz('sunrise'); タイムゾーン付きTIMEカラム
$table->timestamp('added_on'); TIMESTAMPカラム
$table->timestampTz('added_on'); タイムゾーン付きTIMESTAMPカラム
$table->timestamps(); NULL値可能なcreated_atupdated_atカラム追加
$table->timestampsTz(); タイムゾーン付きのNULL値可能なcreated_atupdated_atカラム追加
$table->tinyIncrements('id'); 符号なしTINYINTを使用した自動増分ID(主キー)
$table->tinyInteger('votes'); TINYINTカラム
$table->unsignedBigInteger('votes'); 符号なしBIGINTカラム
$table->unsignedDecimal('amount', 8, 2); 有効(全体桁数)/小数点以下桁数指定の符号なしDECIMALカラム
$table->unsignedInteger('votes'); 符号なしINTカラム
$table->unsignedMediumInteger('votes'); 符号なしMEDIUMINTカラム
$table->unsignedSmallInteger('votes'); 符号なしSMALLINTカラム
$table->unsignedTinyInteger('votes'); 符号なしTINYINTカラム
$table->uuid('id'); UUIDカラム
$table->year('birth_year'); YEARカラム

カラム修飾子

上記のカラムタイプに付け加え、カラムを追加するときに使用できる様々な修飾子もあります。たとえばカラムを「NULL値設定可能(nullable)」にしたい場合は、nullableメソッドを使います。

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->nullable();
});

下表が使用可能なカラム修飾子の一覧です。インデックス修飾子は含まれていません。

修飾子 説明
->after('column') 指定カラムの次に他のカラムを設置(MySQLのみ)
->autoIncrement() 整数カラムを自動増分ID(主キー)へ設定
->charset('utf8') カラムへキャラクタセットを指定(MySQLのみ)
->collation('utf8_unicode_ci') カラムへコロケーションを指定(MySQL/SQL Serverのみ)
->comment('my comment') カラムにコメント追加(MySQLのみ)
->default($value) カラムのデフォルト(default)値設定
->first() カラムをテーブルの最初(first)に設置する(MySQLのみ)
->nullable($value = true) (デフォルトで)NULL値をカラムに挿入する
->storedAs($expression) stored generatedカラムを生成(MySQLのみ)
->unsigned() 整数カラムを符号なしに設定(MySQLのみ)
->useCurrent() TIMESTAMPカラムのデフォルト値をCURRENT_TIMESTAMPに指定
->virtualAs($expression) virtual generatedカラムを生成(MySQLのみ)

カラム変更

動作要件

カラムを変更する前に、composer.jsonファイルでdoctrine/dbalを確実に追加してください。Doctrine DBALライブラリーは現在のカラムの状態を決め、指定されたカラムに対する修正を行うSQLクエリを生成するために、使用しています。

composer require doctrine/dbal

カラム属性の変更

changeメソッドは存在するカラムを新しいタイプへ変更するか、カラムの属性を変えます。たとえば文字列の長さを増やしたい場合です。changeの実例を見てもらうため、nameカラムのサイズを25から50へ増やしてみます。

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->change();
});

さらにカラムをNULL値設定可能にしてみましょう。

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->nullable()->change();
});

Note: 以降のカラムタイプのみ変更可能です:bigInteger、binary、boolean、date、dateTime、dateTimeTz、decimal、integer、json、longText、mediumText、smallInteger、string、text、time、unsignedBigInteger、unsignedInteger and unsignedSmallInteger

カラム名変更

カラム名を変更するには、renameColumnメソッドをスキーマビルダで使用してください。カラム名を変更する前に、composer.jsonファイルでdoctrine/dbalを依存パッケージとして追加してください。

Schema::table('users', function (Blueprint $table) {
    $table->renameColumn('from', 'to');
});

Note: カラムタイプがenumのテーブル中のカラム名変更は、現在サポートしていません。

カラム削除

カラムをドロップするには、スキーマビルダのdropColumnメソッドを使用します。SQLiteデータベースからカラムをドロップする場合は、事前にcomposer.jsonファイルへdoctrine/dbal依存パッケージを追加してください。その後にライブラリーをインストールするため、ターミナルでcomposer updateを実行してください。

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('votes');
});

dropColumnメソッドにカラム名の配列を渡せば、テーブルから複数のカラムをドロップできます。

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn(['votes', 'avatar', 'location']);
});

Note: SQLite使用時に、一つのマイグレーションによる複数カラム削除/変更はサポートされていません。

利用可能な別名コマンド

各インデックスメソッドは、第2引数にオプショナルでインデックス名を指定できます。初略した場合、名前はテーブルとカラムの名前から生成されます。

コマンド 説明
$table->dropRememberToken(); remember_tokenカラムのドロップ
$table->dropSoftDeletes(); deleted_atカラムのドロップ
$table->dropSoftDeletesTz(); dropSoftDeletes()メソッドの別名
$table->dropTimestamps(); created_atupdated_atカラムのドロップ
$table->dropTimestampsTz(); dropTimestamps()メソッドの別名

インデックス

インデックス作成

スキーマビルダは様々なインデックスタイプをサポートしています。まず指定したカラムの値を一意にする例を見てください。インデックスを作成するには、カラム定義にuniqueメソッドをチェーンで付け加えます。

$table->string('email')->unique();

もしくはカラム定義の後でインデックスを作成することも可能です。例を見てください。

$table->unique('email');

インデックスメソッドにカラムの配列を渡し、複合インデックスを作成することもできます。

$table->index(['account_id', 'created_at']);

Laravelは自動的に、わかりやすいインデックス名を付けます。しかしメソッドの第2引数で、名前を指定することもできます。

$table->unique('email', 'unique_email');

使用可能なインデックスタイプ

コマンド 説明
$table->primary('id'); 主キー追加
$table->primary(['id', 'parent_id']); 複合キー追加
$table->unique('email'); uniqueキー追加
$table->index('state'); 基本的なインデックス追加
$table->spatialIndex('location'); 空間インデックス追加(SQLite以外)

インデックス長とMySQL/MariaDB

Laravelはデータベース中への「絵文字」保存をサポートするため、デフォルトでutf8mb4文字セットを使っています。バージョン5.7.7より古いMySQLや、バージョン10.2.2より古いMariaDBを使用している場合、マイグレーションにより生成されるデフォルトのインデックス用文字列長を明示的に設定する必要があります。AppServiceProvider中でSchema::defaultStringLengthを呼び出してください。

use Illuminate\Support\Facades\Schema;

/**
 * 全アプリケーションサービスの初期起動処理
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}

もしくは、データベースのinnodb_large_prefixオプションを有効にする方法もあります。このオプションを各自に有効にする方法は、使用するデータベースのドキュメントを参照してください。

インデックス名変更

インデックス名を変更するためには、renameIndexメソッドを使用します。このメソッドは最初の引数として現在のインデックス名を受け取り、2つ目の引数として変更後の名前を受け取ります。

$table->renameIndex('from', 'to')

インデックス削除

インデックスを削除する場合はインデックスの名前を指定します。Laravelはデフォルトで意味が通る名前をインデックスに付けます。テーブル名、インデックスしたカラム名、インデックスタイプをつなげたものです。いくつか例をご覧ください。

コマンド 説明
$table->dropPrimary('users_id_primary'); "users"テーブルから主キーを削除
$table->dropUnique('users_email_unique'); "users"テーブルからユニークキーを削除
$table->dropIndex('geo_state_index'); "geo"テーブルから基本インデックスを削除
$table->dropSpatialIndex('geo_location_spatialindex'); "geo"テーブルから空間インデックスを削除(SQLite以外)

カラムの配列をインデックス削除メソッドに渡すと、テーブル、カラム、キータイプに基づき、命名規則に従ったインデックス名が生成されます。

Schema::table('geo', function (Blueprint $table) {
    $table->dropIndex(['state']); // 'geo_state_index'インデックスを削除
});

外部キー制約

Laravelはデータベースレベルの整合性を強制するために、テーブルに対する外部キー束縛の追加も提供しています。たとえばusersテーブルのidカラムを参照する、postsテーブルのuser_idカラムを定義してみましょう。

Schema::table('posts', function (Blueprint $table) {
    $table->unsignedInteger('user_id');

    $table->foreign('user_id')->references('id')->on('users');
});

さらに束縛に対して「デリート時(on delete)」と「更新時(on update)」に対する処理をオプションとして指定できます。

$table->foreign('user_id')
      ->references('id')->on('users')
      ->onDelete('cascade');

外部キーを削除するには、dropForeignメソッドを使用します。他のインデックスで使用されるものと似た命名規則が、外部キーにも使用されています。つまりテーブル名とカラム名をつなげ、"_foreign"を最後につけた名前になります。

$table->dropForeign('posts_user_id_foreign');

もしくは配列値を渡せば、削除時に自動的に命名規則に従った名前が使用されます。

$table->dropForeign(['user_id']);

以下のメソッドにより、マイグレーション中の外部キー制約の有効/無効を変更できます。

Schema::enableForeignKeyConstraints();

Schema::disableForeignKeyConstraints();

ドキュメント章別ページ

公式パッケージ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

バージョン

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる