イントロダクション
マイグレーションとはデータベースのバージョンコントロールのようなもので、チームでアプリケーションデータベースのスキーマを簡単に更新し共有できるようにしてくれます。通常、マイグレーションはアプリケーションのデータベーススキーマを簡単に構築できるようにする、Laravelのスキーマビルダーと一緒に使用します。
LaravelのSchema
ファサードはテーブルの作成や操作をどのデータベースエンジンを使うかに関わらずサポートします。Laravelがサポートしているデータベースシステム全部で同じ記述法と書きやすいAPIを共用できます。
マイグレーション生成
make:migration
Artisanコマンドを使いマイグレーションを生成できます。
php artisan make:migration create_users_table
マイグレーションはdatabase/migrations
フォルダーに設置されます。マイグレーションの実行順をフレームワークに知らせるため、名前にタイムスタンプが含まれています。
--table
と--create
オプションも、テーブル名とマイグレーションで新しいテーブルを生成するかを指定するために使用できます。これらのオプションは生成するマイグレーションスタブの中へ指定したテーブルをただ予め埋め込みます。
php artisan make:migration add_votes_to_users_table --table=users
php artisan make:migration create_users_table --create=users
マイグレーションの生成出力先のパスを指定したい場合は、make:migrate
コマンドの実行時に--path
オプションを付けてください。パスはアプリケーションのベースパスからの相対位置です。
マイグレーション構造
マイグレーションはup
とdown
の2メソッドを含んでいます。up
メソッドは新しいテーブル、カラム、インデックスをデータベースに追加するために使用し、一方のdown
メソッドはup
メソッドが行った操作を元に戻します。
両方のメソッドで記述的にテーブルを作成したり、変更したりできるLaravelスキーマビルダーを使えます。Schema
ビルダーで使用できる全メソッドは、このドキュメント後半で確認してください。例としてflights
テーブルを作成するマイグレーションを見てください。
<?php
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コマンドを使用します。Homestead仮想マシーンを使用している場合は、VMの中でこのコマンドを実行してください。
php artisan migrate
マイグレーション中に"class not
found"エラーが出る場合は、composer dump-autoload
を実行し、その後に再実行してください。
実働環境でのマイグレーション強制
いくつかのマイグレーション操作は破壊的です。つまりデーターを失う可能性があります。実働環境(production)のデータベースでこうしたコマンドが実行されることから保護するために、コマンド実行前に確認のプロンプトが表示されます。コマンド実行時のプロンプトを出さないためには、--force
フラグを指定してください。
php artisan migrate --force
マイグレーションロールバック
最後のマイグレーション「操作」をロールバックしたい場合は、rollback
コマンドを使います。このロールバックで注意してもらいたのは、「一度」に実行した最後のマイグレーションを元に戻すため、複数のマイグレーションファイル分の操作が巻き戻されることがある点です。
php artisan migrate:rollback
migrate:reset
コマンドはアプリケーション全部のマイグレーションをロールバックします。
php artisan migrate:reset
rollbackとmigrateの1コマンド実行
migrate:refresh
コマンドは全部のデータベースマイグレーションを最初にロールバックし、それからmigrate
コマンドを実行します。このコマンドはデータベース全体を作り直すために便利です。
php artisan migrate:refresh
php artisan migrate:refresh --seed
マイグレーション記述
テーブル作成
新しいデータベーステーブルを作成するには、Schema
ファサードのcreate
メソッドを使用します。create
メソッドは引数を2つ取ります。最初はテーブルの名前で、2つ目は新しいテーブルを定義するために使用するBlueprint
オブジェクトを受け取る「クロージャー」です。
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
});
もちろんテーブル作成時には、テーブルのカラムを定義するためにスキーマビルダーのカラムメソッドをどれでも利用できます。
テーブル/カラムの存在チェック
hasTable
やhasColumn
メソッドを使えば、テーブルやカラムの存在を簡単にチェックできます。
if (Schema::hasTable('users')) {
//
}
if (Schema::hasColumn('users', 'email')) {
//
}
接続とストレージエンジン
デフォルト接続以外のデータベース接続でスキーマ操作を行いたい場合は、connection
メソッドを使ってください。
Schema::connection('foo')->create('users', function ($table) {
$table->increments('id');
});
テーブルのストレージエンジンを指定する場合は、スキーマビルダーのengine
プロパティを設定します。
Schema::create('users', function ($table) {
$table->engine = 'InnoDB';
$table->increments('id');
});
テーブルリネーム/削除
既存のデータベーステーブルの名前を変えたい場合は、rename
メソッドを使います。
Schema::rename($from, $to);
存在するテーブルを削除する場合は、drop
かdropIfExists
メソッドを使います。
Schema::drop('users');
Schema::dropIfExists('users');
カラム作成
存在するテーブルを更新するには、Schema
ファサードのtable
メソッドを使います。create
メソッドと同様にtable
メソッドは2つの引数を取ります。テーブルの名前と、テーブルにカラムを追加するために使用するBlueprint
インスタンスを受け取る「クロージャー」です。
Schema::table('users', function ($table) {
$table->string('email');
});
使用できるカラムタイプ
当然ながらスキーマビルダーは、テーブルを構築する時に使用する様々なカラムタイプを持っています。
コマンド | 説明 |
---|---|
$table->bigIncrements('id'); |
「符号なしBIGINT」を使用した自動増分ID(主キー) |
$table->bigInteger('votes'); |
BIGINTカラム |
$table->binary('data'); |
BLOBカラム |
$table->boolean('confirmed'); |
BOOLEANカラム |
$table->char('name', 4); |
長さを指定するCHARカラム |
$table->date('created_at'); |
DATEカラム |
$table->dateTime('created_at'); |
DATETIMEカラム |
$table->decimal('amount', 5, 2); |
有効/小数点以下桁数指定のDECIMALカラム |
$table->double('column', 15, 8); |
15桁、小数点以下8桁のDOUBLEカラム |
$table->enum('choices', ['foo', 'bar']); |
ENUMカラム |
$table->float('amount'); |
FLOATカラム |
$table->increments('id'); |
「符号なしINT」を使用した自動増分ID(主キー) |
$table->integer('votes'); |
INTEGERカラム |
$table->json('options'); |
JSONフィールド |
$table->jsonb('options'); |
JSONBフィールド |
$table->longText('description'); |
LONGTEXTカラム |
$table->mediumInteger('numbers'); |
MEDIUMINTカラム |
$table->mediumText('description'); |
MEDIUMTEXTカラム |
$table->morphs('taggable'); |
INTERGERのtaggable_id と文字列のtaggable_type を追加 |
$table->nullableTimestamps(); |
NULL値を許す以外、timestamps() と同じ |
$table->rememberToken(); |
VARCHAR(100) NULLのremember_token を追加 |
$table->smallInteger('votes'); |
SMALLINTカラム |
$table->softDeletes(); |
ソフトデリートのためのdeleted_at カラム追加 |
$table->string('email'); |
VARCHARカラム |
$table->string('name', 100); |
長さ指定のVARCHARカラム |
$table->text('description'); |
TEXTカラム |
$table->time('sunrise'); |
TIMEカラム |
$table->tinyInteger('numbers'); |
TINYINTカラム |
$table->timestamp('added_on'); |
TIMESTAMPカラム |
$table->timestamps(); |
created_at とupdate_at カラムの追加 |
$table->uuid('id'); |
データベース向けのUUID類似値 |
カラム修飾子
上記のカラムタイプに付け加え、カラムを追加するときに使用できる様々な修飾子もあります。たとえばカラムを「NULL値設定可能(nullable)」にしたい場合は、nullable
メソッドを使います。
Schema::table('users', function ($table) {
$table->string('email')->nullable();
});
下表が使用可能なカラム修飾子の一覧です。インデックス修飾子は含まれていません。
修飾子 | 説明 |
---|---|
->first() |
カラムをテーブルの最初(first)に設置する(MySQLのみ) |
->after('column') |
指定カラムの次にカラムを設置する(MySQLのみ) |
->nullable() |
カラムにNULL値を許す |
->default($value) |
カラムのデフォルト(default)値設定 |
->unsigned() |
整数(integer)を符号(unsigned) |
カラム変更
動作要件
カラムを変更する前に、composer.json
ファイルでdoctrine/dbal
を確実に追加してください。Doctrine
DBALライブラリーは現在のカラムの状態を決め、指定されたカラムに対する修正を行うSQLを生成します。
カラム属性の変更
change
メソッドは存在するカラムを新しいタイプへ変更するか、カラムの属性を変えます。たとえば文字列の長さを増やしたい場合です。change
の実例を見てもらうため、name
カラムのサイズを25から50へ増やしてみます。
Schema::table('users', function ($table) {
$table->string('name', 50)->change();
});
さらにカラムをNULL値設定可能にしてみましょう。
Schema::table('users', function ($table) {
$table->string('name', 50)->nullable()->change();
});
カラム名変更
カラム名を変更するには、renameColumn
メソッドをスキーマビルダーで使用してください。カラム名を変更する前に、composer.json
ファイルでdoctrine/dbal
を依存パッケージとして追加してください。
Schema::table('users', function ($table) {
$table->renameColumn('from', 'to');
});
注意:
enum
カラムを含んでいるテーブルのカラム名変更は現在サポートしていません。
カラム削除
カラムをドロップするには、スキーマビルダーのdropColumn
メソッドを使用します。
Schema::table('users', function ($table) {
$table->dropColumn('votes');
});
dropColumn
メソッドにカラム名の配列を渡せば、テーブルから複数のカラムをドロップできます。
Schema::table('users', function ($table) {
$table->dropColumn(['votes', 'avatar', 'location']);
});
注意 SQLiteデータベースからカラムをドロップする場合は、事前に
composer.json
ファイルへdoctrine/dbal
依存パッケージを追加してください。その後にライブラリーをインストールするため、composer update
を実行してください。
注意: SQLite使用時に、一つのマイグレーションによる複数カラム削除/変更はサポートされていません。
インデックス作成
スキーマビルダーは様々なインデックスタイプをサポートしています。まず指定したカラムの値を一意にする例を見てください。インデックスを作成するには、カラム定義にunique
メソッドをチェーンで付け加えるだけです。
$table->string('email')->unique();
もしくはカラム定義の後でインデックスを作成することも可能です。例を見てください。
$table->unique('email');
インデックスメソッドにカラムの配列を渡し、複合インデックスを作成することもできます。
$table->index(['account_id', 'created_at']);
使用可能なインデックスタイプ
コマンド | 説明 |
---|---|
$table->primary('id'); |
主キー追加 |
$table->primary(['first', 'last']); |
複合キー追加 |
$table->unique('email'); |
uniqueキー追加 |
$table->index('state'); |
基本的なインデックス追加 |
インデックス削除
インデックスを削除する場合はインデックスの名前を指定します。Laravelはデフォルトで意味が通る名前をインデックスに付けます。シンプルにテーブル名、インデックスしたカラム名、インデックスタイプをつなげたものです。いくつか例をご覧ください。
コマンド | 説明 |
---|---|
$table->dropPrimary('users_id_primary'); |
"users"テーブルから主キーを削除 |
$table->dropUnique('users_email_unique'); |
"users"テーブルからユニークキーを削除 |
$table->dropIndex('geo_state_index'); |
"geo"テーブルから基本インデックスを削除 |
カラムの配列をインデックス削除メソッドに渡すと、テーブル、カラム、キータイプに基づき、命名規則に従ったインデックス名が生成されます。
Schema::table('geo', function ($table) {
$table->dropIndex(['state']); // Drops index 'geo_state_index'
});
外部キー制約
Laravelはデータベースレベルの整合性を強制するために、テーブルに対する外部キー束縛の追加も提供しています。たとえばusers
テーブルのid
カラムを参照する、posts
テーブルのuser_id
カラムを定義してみましょう。
Schema::table('posts', function ($table) {
$table->integer('user_id')->unsigned();
$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']);