#はじめに
マイグレーションはデータベースのバージョン管理のようなもので、チームでアプリケーションのデータベーススキーマ定義を共有・管理できます。ソース管理から変更を取り込んだ後に、チームメンバーにローカルのデータベーススキーマに手動でカラムを追加するよう指示したことがあれば、マイグレーションが解決する問題に直面したことになります。
Laravel の Schema ファサード は、Laravel がサポートするすべてのデータベースシステムでテーブルの作成や操作をデータベースに依存せずにサポートします。通常、マイグレーションはこのファサードを使ってデータベースのテーブルやカラムを作成・変更します。
#マイグレーションの生成
make:migration Artisanコマンドを使ってデータベースマイグレーションを生成できます。新しいマイグレーションは database/migrations ディレクトリに配置されます。各マイグレーションファイル名にはタイムスタンプが含まれており、Laravel はこれを使ってマイグレーションの実行順序を判断します。
php artisan make:migration create_flights_table
Laravel はマイグレーション名からテーブル名や新規テーブル作成かどうかを推測しようとします。マイグレーション名からテーブル名を特定できれば、生成されるマイグレーションファイルにそのテーブル名があらかじめ入力されます。そうでなければ、マイグレーションファイル内で手動でテーブル名を指定してください。
生成されるマイグレーションのパスをカスタム指定したい場合は、make:migration コマンド実行時に --path オプションを使えます。指定するパスはアプリケーションのベースパスからの相対パスである必要があります。
マイグレーションのスタブは スタブ公開 を使ってカスタマイズできます。
#マイグレーションの統合(スクワッシュ)
アプリケーションを構築していくと、マイグレーションがどんどん増えていきます。これにより database/migrations ディレクトリが数百のマイグレーションで膨れ上がることがあります。必要に応じて、マイグレーションを1つのSQLファイルに「スクワッシュ」できます。開始するには schema:dump コマンドを実行してください。
php artisan schema:dump
# 現在のデータベーススキーマをダンプし、既存のマイグレーションをすべて削除します...
php artisan schema:dump --prune
このコマンドを実行すると、Laravel はアプリケーションの database/schema ディレクトリに「スキーマ」ファイルを書き込みます。スキーマファイル名はデータベース接続名に対応します。マイグレーションを実行し、まだ実行されていないマイグレーションがない場合、Laravel はまず使用中のデータベース接続のスキーマファイル内のSQL文を実行します。その後、スキーマダンプに含まれていなかった残りのマイグレーションを実行します。
アプリケーションのテストが通常のローカル開発時とは異なるデータベース接続を使う場合、その接続でスキーマファイルをダンプしておく必要があります。通常のローカル開発用接続のスキーマダンプ後に行うとよいでしょう。
php artisan schema:dump
php artisan schema:dump --database=testing --prune
データベーススキーマファイルはソース管理にコミットしてください。そうすることで、新しいチームメンバーがアプリケーションの初期データベース構造を素早く作成できます。
マイグレーションのスクワッシュは MySQL、PostgreSQL、SQLite のみ対応しており、データベースのコマンドラインクライアントを利用します。
#マイグレーションの構造
マイグレーションクラスは up と down の2つのメソッドを持ちます。up メソッドは新しいテーブル、カラム、インデックスを追加するために使い、down メソッドは up の操作を元に戻すために使います。
両メソッド内で Laravel のスキーマビルダーを使ってテーブルを表現的に作成・変更できます。Schema ビルダーで利用可能なすべてのメソッドはドキュメントを参照してください。例えば、以下のマイグレーションは flights テーブルを作成します。
<?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('flights', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('airline');
$table->timestamps();
});
}
/**
* マイグレーションを元に戻します。
*/
public function down(): void
{
Schema::drop('flights');
}
};
#マイグレーションの接続設定
マイグレーションがアプリケーションのデフォルトデータベース接続以外の接続を使う場合は、マイグレーションの $connection プロパティを設定してください。
/**
* マイグレーションで使用するデータベース接続。
*
* @var string
*/
protected $connection = 'pgsql';
/**
* マイグレーションを実行します。
*/
public function up(): void
{
// ...
}
#マイグレーションの実行
未実行のすべてのマイグレーションを実行するには、migrate Artisanコマンドを実行してください。
php artisan migrate
これまでに実行されたマイグレーションを確認したい場合は、migrate:status Artisanコマンドを使えます。
php artisan migrate:status
マイグレーションで実行されるSQL文を実際に実行せずに確認したい場合は、migrate コマンドに --pretend フラグを付けてください。
php artisan migrate --pretend
#マイグレーション実行の分離
複数サーバーにアプリケーションをデプロイし、デプロイ時にマイグレーションを実行する場合、同時に複数のサーバーがマイグレーションを実行しないようにしたいでしょう。そのために、migrate コマンド実行時に isolated オプションを使えます。
isolated オプションを指定すると、Laravel はアプリケーションのキャッシュドライバーを使ってアトミックロックを取得してからマイグレーションを実行します。そのロックが保持されている間に他の migrate コマンド実行は実行されませんが、コマンドは成功終了コードで終了します。
php artisan migrate --isolated
この機能を利用するには、アプリケーションのデフォルトキャッシュドライバーが memcached、redis、dynamodb、database、file、または array のいずれかである必要があります。また、すべてのサーバーが同じ中央キャッシュサーバーと通信している必要があります。
#本番環境でのマイグレーション強制実行
一部のマイグレーション操作は破壊的で、データを失う可能性があります。これらのコマンドを本番データベースで実行する際は確認を求められます。確認なしで強制実行したい場合は、--force フラグを使ってください。
php artisan migrate --force
#マイグレーションのロールバック
最新のマイグレーション操作をロールバックするには、rollback Artisanコマンドを使います。このコマンドは最後の「バッチ」のマイグレーションをロールバックします。バッチには複数のマイグレーションファイルが含まれる場合があります。
php artisan migrate:rollback
rollback コマンドに step オプションを指定すると、指定した数だけマイグレーションをロールバックできます。例えば、以下のコマンドは直近の5つのマイグレーションをロールバックします。
php artisan migrate:rollback --step=5
rollbackコマンドに batch オプションを指定することで、特定の「バッチ」のマイグレーションをロールバックできます。batch オプションは、アプリケーションの migrations データベーステーブル内のバッチ値に対応します。たとえば、次のコマンドはバッチ3に属するすべてのマイグレーションをロールバックします:
php artisan migrate:rollback --batch=3
マイグレーションで実行されるSQL文を実際に実行せずに確認したい場合は、migrate:rollback コマンドに --pretend フラグを付けてください。
php artisan migrate:rollback --pretend
migrate:reset コマンドはアプリケーションのすべてのマイグレーションをロールバックします。
php artisan migrate:reset
#ロールバックとマイグレーションを一括で実行
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
デフォルトでは migrate:fresh コマンドはデフォルトのデータベース接続のテーブルのみ削除します。ただし、--database オプションを使ってマイグレーション対象のデータベース接続を指定できます。接続名はアプリケーションの database 設定ファイルに定義された接続名に対応します。
php artisan migrate:fresh --database=admin
migrate:fresh コマンドはテーブルのプレフィックスに関係なくすべてのテーブルを削除します。このコマンドは他のアプリケーションと共有しているデータベースでの開発時に注意して使ってください。
#テーブル
#テーブルの作成
新しいデータベーステーブルを作成するには、Schema ファサードの create メソッドを使います。create メソッドは2つの引数を受け取ります。1つ目はテーブル名、2つ目は Blueprint オブジェクトを受け取るクロージャで、新しいテーブルの定義に使います。
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email');
$table->timestamps();
});
テーブル作成時には、スキーマビルダーのカラムメソッドを使ってテーブルのカラムを定義できます。
#テーブル・カラムの存在確認
hasTable と hasColumn メソッドを使ってテーブルやカラムの存在を確認できます。
if (Schema::hasTable('users')) {
// "users" テーブルが存在します...
}
if (Schema::hasColumn('users', 'email')) {
// "users" テーブルが存在し、"email" カラムがあります...
}
#データベース接続とテーブルオプション
アプリケーションのデフォルト接続以外のデータベース接続でスキーマ操作を行いたい場合は、connection メソッドを使います。
Schema::connection('sqlite')->create('users', function (Blueprint $table) {
$table->id();
});
また、テーブル作成時にいくつかのプロパティやメソッドで他の設定もできます。MySQLを使う場合、engine プロパティでストレージエンジンを指定できます。
Schema::create('users', function (Blueprint $table) {
$table->engine = 'InnoDB';
// ...
});
MySQLを使う場合、charset と collation プロパティで文字セットと照合順序を指定できます。
Schema::create('users', function (Blueprint $table) {
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
// ...
});
temporary メソッドは、テーブルを「一時的なもの」と指定するために使えます。一時テーブルは現在の接続のデータベースセッションでのみ見え、接続が閉じられると自動的に削除されます。
Schema::create('calculations', function (Blueprint $table) {
$table->temporary();
// ...
});
データベーステーブルに「コメント」を追加したい場合は、テーブルインスタンスの comment メソッドを呼び出せます。テーブルコメントは現在、MySQL と Postgres のみサポートされています。
Schema::create('calculations', function (Blueprint $table) {
$table->comment('Business calculations');
// ...
});
#テーブルの更新
Schema ファサードの table メソッドは、既存のテーブルを更新するために使えます。create メソッドと同様に、table メソッドはテーブル名と、テーブルにカラムやインデックスを追加するための Blueprint インスタンスを受け取るクロージャの2つの引数を取ります。
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('users', function (Blueprint $table) {
$table->integer('votes');
});
#テーブルの名前変更 / 削除
既存のデータベーステーブルの名前を変更するには、rename メソッドを使います。
use Illuminate\Support\Facades\Schema;
Schema::rename($from, $to);
既存のテーブルを削除するには、drop または dropIfExists メソッドを使えます。
Schema::drop('users');
Schema::dropIfExists('users');
#外部キー付きテーブルの名前変更
テーブルの名前を変更する前に、マイグレーションファイルで外部キー制約に明示的な名前が付けられていることを確認してください。Laravel が規約に基づく名前を自動で付けている場合、外部キー制約名は古いテーブル名を参照したままになります。
#カラム
#カラムの作成
Schema ファサードの table メソッドは、既存のテーブルを更新するために使えます。create メソッドと同様に、table メソッドはテーブル名と、テーブルにカラムを追加するための Illuminate\Database\Schema\Blueprint インスタンスを受け取るクロージャの2つの引数を取ります。
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('users', function (Blueprint $table) {
$table->integer('votes');
});
#利用可能なカラムタイプ
スキーマビルダーの Blueprint は、データベーステーブルに追加できるさまざまなカラムタイプに対応した多くのメソッドを提供します。利用可能なメソッドは以下の表に一覧されています。
<style> .collection-method-list > p { columns: 10.8em 3; -moz-columns: 10.8em 3; -webkit-columns: 10.8em 3; } .collection-method-list a { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .collection-method code { font-size: 14px; } .collection-method:not(.first-collection-method) { margin-top: 50px; } </style>bigIncrements bigInteger binary boolean char dateTimeTz dateTime date decimal double enum float foreignId foreignIdFor foreignUlid foreignUuid geometryCollection geometry id increments integer ipAddress json jsonb lineString longText macAddress mediumIncrements mediumInteger mediumText morphs multiLineString multiPoint multiPolygon nullableMorphs nullableTimestamps nullableUlidMorphs nullableUuidMorphs point polygon rememberToken set smallIncrements smallInteger softDeletesTz softDeletes string text timeTz time timestampTz timestamp timestampsTz timestamps tinyIncrements tinyInteger tinyText unsignedBigInteger unsignedDecimal unsignedInteger unsignedMediumInteger unsignedSmallInteger unsignedTinyInteger ulidMorphs uuidMorphs ulid uuid year
#bigIncrements() {.collection-method .first-collection-method}
bigIncrements メソッドは、自動増分の UNSIGNED BIGINT(主キー)相当のカラムを作成します。
$table->bigIncrements('id');
#bigInteger() {.collection-method}
bigInteger メソッドは、BIGINT 相当のカラムを作成します。
$table->bigInteger('votes');
#binary() {.collection-method}
binary メソッドは、BLOB 相当のカラムを作成します。
$table->binary('photo');
#boolean() {.collection-method}
boolean メソッドは、BOOLEAN 相当のカラムを作成します。
$table->boolean('confirmed');
#char() {.collection-method}
char メソッドは、指定した長さの CHAR 相当のカラムを作成します。
$table->char('name', 100);
#dateTimeTz() {.collection-method}
dateTimeTz メソッドは、タイムゾーン付きの DATETIME 相当のカラムを作成します。精度(小数点以下の桁数)を指定可能です。
$table->dateTimeTz('created_at', $precision = 0);
#dateTime() {.collection-method}
dateTime メソッドは、DATETIME 相当のカラムを作成します。精度(小数点以下の桁数)を指定可能です。
$table->dateTime('created_at', $precision = 0);
#date() {.collection-method}
date メソッドは、DATE 相当のカラムを作成します。
$table->date('created_at');
#decimal() {.collection-method}
decimal メソッドは、指定した精度(全桁数)とスケール(小数点以下の桁数)を持つ DECIMAL 相当のカラムを作成します。
$table->decimal('amount', $precision = 8, $scale = 2);
#double() {.collection-method}
double メソッドは、指定した精度(全桁数)とスケール(小数点以下の桁数)を持つ DOUBLE 相当のカラムを作成します。
$table->double('amount', 8, 2);
#enum() {.collection-method}
enum メソッドは、指定した有効な値のセットを持つ ENUM 相当のカラムを作成します。
$table->enum('difficulty', ['easy', 'hard']);
#float() {.collection-method}
float メソッドは、指定した精度(全桁数)とスケール(小数点以下の桁数)を持つ FLOAT 相当のカラムを作成します。
$table->float('amount', 8, 2);
#foreignId() {.collection-method}
foreignId メソッドは、UNSIGNED BIGINT 相当のカラムを作成します。
$table->foreignId('user_id');
#foreignIdFor() {.collection-method}
foreignIdFor メソッドは、指定したモデルクラスに対応する {column}_id 相当のカラムを追加します。カラムタイプはモデルのキータイプに応じて UNSIGNED BIGINT、CHAR(36)、または CHAR(26) になります。
$table->foreignIdFor(User::class);
#foreignUlid() {.collection-method}
foreignUlid メソッドは、ULID 相当のカラムを作成します。
$table->foreignUlid('user_id');
#foreignUuid() {.collection-method}
foreignUuid メソッドは、UUID 相当のカラムを作成します。
$table->foreignUuid('user_id');
#geometryCollection() {.collection-method}
geometryCollection メソッドは、GEOMETRYCOLLECTION 相当のカラムを作成します。
$table->geometryCollection('positions');
#geometry() {.collection-method}
geometry メソッドは、GEOMETRY 相当のカラムを作成します。
$table->geometry('positions');
#id() {.collection-method}
id メソッドは bigIncrements メソッドのエイリアスです。デフォルトでは id カラムを作成しますが、異なる名前を付けたい場合はカラム名を渡せます。
$table->id();
#increments() {.collection-method}
increments メソッドは、自動増分の UNSIGNED INTEGER 相当のカラムを主キーとして作成します。
$table->increments('id');
#integer() {.collection-method}
integer メソッドは、INTEGER 相当のカラムを作成します。
$table->integer('votes');
#ipAddress() {.collection-method}
ipAddress メソッドは、VARCHAR 相当のカラムを作成します。
$table->ipAddress('visitor');
Postgres を使用する場合は、INET カラムが作成されます。
#json() {.collection-method}
json メソッドは、JSON 相当のカラムを作成します。
$table->json('options');
#jsonb() {.collection-method}
jsonb メソッドは、JSONB 相当のカラムを作成します。
$table->jsonb('options');
#lineString() {.collection-method}
lineString メソッドは、LINESTRING 相当のカラムを作成します。
$table->lineString('positions');
#longText() {.collection-method}
longText メソッドは、LONGTEXT 相当のカラムを作成します。
$table->longText('description');
#macAddress() {.collection-method}
macAddress メソッドは、MACアドレスを格納するためのカラムを作成します。PostgreSQL のように専用のカラムタイプを持つデータベースもありますが、他のデータベースでは文字列相当のカラムになります。
$table->macAddress('device');
#mediumIncrements() {.collection-method}
mediumIncrements メソッドは、自動増分の UNSIGNED MEDIUMINT 相当のカラムを主キーとして作成します。
$table->mediumIncrements('id');
#mediumInteger() {.collection-method}
mediumInteger メソッドは、MEDIUMINT 相当のカラムを作成します。
$table->mediumInteger('votes');
#mediumText() {.collection-method}
mediumText メソッドは、MEDIUMTEXT 相当のカラムを作成します。
$table->mediumText('description');
#morphs() {.collection-method}
morphs メソッドは、{column}_id 相当のカラムと {column}_type の VARCHAR 相当のカラムを追加する便利なメソッドです。{column}_id のカラムタイプはモデルのキータイプに応じて UNSIGNED BIGINT、CHAR(36)、または CHAR(26) になります。
このメソッドは、多態的な Eloquent リレーションシップ に必要なカラムを定義する際に使います。以下の例では、taggable_id と taggable_type のカラムが作成されます。
$table->morphs('taggable');
#multiLineString() {.collection-method}
multiLineString メソッドは、MULTILINESTRING 相当のカラムを作成します。
$table->multiLineString('positions');
#multiPoint() {.collection-method}
multiPoint メソッドは、MULTIPOINT 相当のカラムを作成します。
$table->multiPoint('positions');
#multiPolygon() {.collection-method}
multiPolygon メソッドは、MULTIPOLYGON 相当のカラムを作成します。
$table->multiPolygon('positions');
#nullableTimestamps() {.collection-method}
nullableTimestamps メソッドは、timestamps メソッドのエイリアスです。
$table->nullableTimestamps(0);
#nullableMorphs() {.collection-method}
このメソッドは morphs メソッドに似ていますが、作成されるカラムは「nullable」になります:
$table->nullableMorphs('taggable');
#nullableUlidMorphs() {.collection-method}
このメソッドは ulidMorphs メソッドに似ていますが、作成されるカラムは「nullable」になります:
$table->nullableUlidMorphs('taggable');
#nullableUuidMorphs() {.collection-method}
このメソッドは uuidMorphs メソッドに似ていますが、作成されるカラムは「nullable」になります:
$table->nullableUuidMorphs('taggable');
#point() {.collection-method}
point メソッドは POINT 相当のカラムを作成します:
$table->point('position');
#polygon() {.collection-method}
polygon メソッドは POLYGON 相当のカラムを作成します:
$table->polygon('position');
#rememberToken() {.collection-method}
rememberToken メソッドは nullable な VARCHAR(100) 相当のカラムを作成し、現在の「remember me」認証トークン を保存するために使います:
$table->rememberToken();
#set() {.collection-method}
set メソッドは指定した有効な値のリストを持つ SET 相当のカラムを作成します:
$table->set('flavors', ['strawberry', 'vanilla']);
#smallIncrements() {.collection-method}
smallIncrements メソッドは自動増分の UNSIGNED SMALLINT 相当のカラムを主キーとして作成します:
$table->smallIncrements('id');
#smallInteger() {.collection-method}
smallInteger メソッドは SMALLINT 相当のカラムを作成します:
$table->smallInteger('votes');
#softDeletesTz() {.collection-method}
softDeletesTz メソッドは nullable な deleted_at の TIMESTAMP(タイムゾーン付き)相当のカラムを、オプションで精度(桁数)を指定して追加します。このカラムは Eloquent の「ソフトデリート」機能で使う deleted_at タイムスタンプを保存するためのものです:
$table->softDeletesTz($column = 'deleted_at', $precision = 0);
#softDeletes() {.collection-method}
softDeletes メソッドは nullable な deleted_at の TIMESTAMP 相当のカラムを、オプションで精度(桁数)を指定して追加します。このカラムは Eloquent の「ソフトデリート」機能で使う deleted_at タイムスタンプを保存するためのものです:
$table->softDeletes($column = 'deleted_at', $precision = 0);
#string() {.collection-method}
string メソッドは指定した長さの VARCHAR 相当のカラムを作成します:
$table->string('name', 100);
#text() {.collection-method}
text メソッドは TEXT 相当のカラムを作成します:
$table->text('description');
#timeTz() {.collection-method}
timeTz メソッドはオプションで精度(桁数)を指定できる、タイムゾーン付きの TIME 相当のカラムを作成します:
$table->timeTz('sunrise', $precision = 0);
#time() {.collection-method}
time メソッドはオプションで精度(桁数)を指定できる TIME 相当のカラムを作成します:
$table->time('sunrise', $precision = 0);
#timestampTz() {.collection-method}
timestampTz メソッドはオプションで精度(桁数)を指定できる、タイムゾーン付きの TIMESTAMP 相当のカラムを作成します:
$table->timestampTz('added_at', $precision = 0);
#timestamp() {.collection-method}
timestamp メソッドはオプションで精度(桁数)を指定できる TIMESTAMP 相当のカラムを作成します:
$table->timestamp('added_at', $precision = 0);
#timestampsTz() {.collection-method}
timestampsTz メソッドはオプションで精度(桁数)を指定できる、created_at と updated_at のタイムゾーン付き TIMESTAMP 相当のカラムを作成します:
$table->timestampsTz($precision = 0);
#timestamps() {.collection-method}
timestamps メソッドはオプションで精度(桁数)を指定できる、created_at と updated_at の TIMESTAMP 相当のカラムを作成します:
$table->timestamps($precision = 0);
#tinyIncrements() {.collection-method}
tinyIncrements メソッドは自動増分の UNSIGNED TINYINT 相当のカラムを主キーとして作成します:
$table->tinyIncrements('id');
#tinyInteger() {.collection-method}
tinyInteger メソッドは TINYINT 相当のカラムを作成します:
$table->tinyInteger('votes');
#tinyText() {.collection-method}
tinyText メソッドは TINYTEXT 相当のカラムを作成します:
$table->tinyText('notes');
#unsignedBigInteger() {.collection-method}
unsignedBigInteger メソッドは UNSIGNED BIGINT 相当のカラムを作成します:
$table->unsignedBigInteger('votes');
#unsignedDecimal() {.collection-method}
unsignedDecimal メソッドはオプションで精度(桁数)とスケール(小数点以下の桁数)を指定できる UNSIGNED DECIMAL 相当のカラムを作成します:
$table->unsignedDecimal('amount', $precision = 8, $scale = 2);
#unsignedInteger() {.collection-method}
unsignedInteger メソッドは UNSIGNED INTEGER 相当のカラムを作成します:
$table->unsignedInteger('votes');
#unsignedMediumInteger() {.collection-method}
unsignedMediumInteger メソッドは UNSIGNED MEDIUMINT 相当のカラムを作成します:
$table->unsignedMediumInteger('votes');
#unsignedSmallInteger() {.collection-method}
unsignedSmallInteger メソッドは UNSIGNED SMALLINT 相当のカラムを作成します:
$table->unsignedSmallInteger('votes');
#unsignedTinyInteger() {.collection-method}
unsignedTinyInteger メソッドは UNSIGNED TINYINT 相当のカラムを作成します:
$table->unsignedTinyInteger('votes');
#ulidMorphs() {.collection-method}
ulidMorphs メソッドは {column}_id の CHAR(26) 相当カラムと {column}_type の VARCHAR 相当カラムを追加する便利なメソッドです。
このメソッドは ULID 識別子を使う多態的な Eloquent リレーションシップ に必要なカラムを定義する際に使います。以下の例では taggable_id と taggable_type カラムが作成されます:
$table->ulidMorphs('taggable');
#uuidMorphs() {.collection-method}
uuidMorphs メソッドは {column}_id の CHAR(36) 相当カラムと {column}_type の VARCHAR 相当カラムを追加する便利なメソッドです。
このメソッドは UUID 識別子を使う多態的な Eloquent リレーションシップ に必要なカラムを定義する際に使います。以下の例では taggable_id と taggable_type カラムが作成されます:
$table->uuidMorphs('taggable');
#ulid() {.collection-method}
ulid メソッドは ULID 相当のカラムを作成します:
$table->ulid('id');
#uuid() {.collection-method}
uuid メソッドは UUID 相当のカラムを作成します:
$table->uuid('id');
#year() {.collection-method}
year メソッドは YEAR 相当のカラムを作成します:
$table->year('birth_year');
#カラム修飾子
上記のカラムタイプに加えて、データベーステーブルにカラムを追加する際に使えるいくつかの「修飾子」があります。例えば、カラムを「nullable」にするには nullable メソッドを使います:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('users', function (Blueprint $table) {
$table->string('email')->nullable();
});
以下の表は利用可能なカラム修飾子の一覧です。このリストには インデックス修飾子 は含まれていません:
| 修飾子 | 説明 |
|---|---|
->after('column') |
既存のカラムの「後」にカラムを配置する(MySQL)。 |
->autoIncrement() |
INTEGER カラムを自動増分(主キー)に設定する。 |
->charset('utf8mb4') |
カラムの文字セットを指定する(MySQL)。 |
->collation('utf8mb4_unicode_ci') |
カラムの照合順序を指定する(MySQL/PostgreSQL/SQL Server)。 |
->comment('my comment') |
カラムにコメントを追加する(MySQL/PostgreSQL)。 |
->default($value) |
カラムの「デフォルト」値を指定する。 |
->first() |
カラムをテーブルの「最初」に配置する(MySQL)。 |
->from($integer) |
自動増分フィールドの開始値を設定する(MySQL / PostgreSQL)。 |
->invisible() |
SELECT * クエリでカラムを「非表示」にする(MySQL)。 |
->nullable($value = true) |
カラムに NULL 値を許可する。 |
->storedAs($expression) |
ストアド生成カラムを作成する(MySQL / PostgreSQL)。 |
->unsigned() |
INTEGER カラムを UNSIGNED に設定する(MySQL)。 |
->useCurrent() |
TIMESTAMP カラムのデフォルト値を CURRENT_TIMESTAMP に設定する。 |
->useCurrentOnUpdate() |
レコード更新時に TIMESTAMP カラムを CURRENT_TIMESTAMP に設定する(MySQL)。 |
->virtualAs($expression) |
仮想生成カラムを作成する(MySQL / PostgreSQL / SQLite)。 |
->generatedAs($expression) |
指定したシーケンスオプションでアイデンティティカラムを作成する(PostgreSQL)。 |
->always() |
アイデンティティカラムの入力よりシーケンス値を優先することを定義する(PostgreSQL)。 |
->isGeometry() |
空間カラムタイプを geometry に設定する(デフォルトは geography)(PostgreSQL)。 |
#デフォルト式
default 修飾子は値または Illuminate\Database\Query\Expression インスタンスを受け入れます。Expression インスタンスを使うと、Laravel が値をクォートで囲むのを防ぎ、データベース固有の関数を使えます。特に JSON カラムにデフォルト値を割り当てる場合に便利です:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* マイグレーションを実行します。
*/
public function up(): void
{
Schema::create('flights', function (Blueprint $table) {
$table->id();
$table->json('movies')->default(new Expression('(JSON_ARRAY())'));
$table->timestamps();
});
}
};
デフォルト式のサポートはデータベースドライバー、データベースのバージョン、フィールドタイプに依存します。詳細はご利用のデータベースのドキュメントを参照してください。
#カラムの順序
MySQL データベースを使用している場合、after メソッドで既存のカラムの後にカラムを追加できます:
$table->after('password', function (Blueprint $table) {
$table->string('address_line1');
$table->string('address_line2');
$table->string('city');
});
#カラムの変更
change メソッドを使うと、既存のカラムの型や属性を変更できます。例えば、string カラムのサイズを大きくしたい場合があります。change メソッドの動作を確認するために、name カラムのサイズを25から50に増やしてみましょう。これを行うには、カラムの新しい状態を定義してから change メソッドを呼び出します:
Schema::table('users', function (Blueprint $table) {
$table->string('name', 50)->change();
});
カラムを変更する際は、保持したい修飾子をすべて明示的に指定する必要があります。指定しなかった属性は削除されます。例えば、unsigned、default、comment 属性を保持したい場合は、それぞれの修飾子を明示的に呼び出してください:
Schema::table('users', function (Blueprint $table) {
$table->integer('votes')->unsigned()->default(1)->comment('my comment')->change();
});
#SQLite でのカラム変更
SQLite データベースを使用している場合、カラムを変更する前に Composer で doctrine/dbal パッケージをインストールする必要があります。Doctrine DBAL ライブラリはカラムの現在の状態を判別し、変更に必要な SQL クエリを生成します:
composer require doctrine/dbal
timestamp メソッドで作成したカラムを変更する場合は、アプリケーションの config/database.php 設定ファイルに以下の設定を追加する必要があります:
use Illuminate\Database\DBAL\TimestampType;
'dbal' => [
'types' => [
'timestamp' => TimestampType::class,
],
],
doctrine/dbal パッケージを使用する場合、以下のカラムタイプのみ変更可能です:bigInteger、binary、boolean、char、date、dateTime、dateTimeTz、decimal、double、integer、json、longText、mediumText、smallInteger、string、text、time、tinyText、unsignedBigInteger、unsignedInteger、unsignedSmallInteger、ulid、および uuid。
#カラムのリネーム
カラム名を変更するには、スキーマビルダーの renameColumn メソッドを使います。
Schema::table('users', function (Blueprint $table) {
$table->renameColumn('from', 'to');
});
#レガシーデータベースでのカラムリネーム
以下のリリースより古いデータベースを使用している場合、カラムをリネームする前に Composer で doctrine/dbal ライブラリをインストールしていることを確認してください。
- MySQL <
8.0.3 - MariaDB <
10.5.2 - SQLite <
3.25.0
#カラムの削除
カラムを削除するには、スキーマビルダーの dropColumn メソッドを使います。
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('votes');
});
複数のカラムを削除する場合は、dropColumn メソッドにカラム名の配列を渡します。
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['votes', 'avatar', 'location']);
});
#レガシーデータベースでのカラム削除
SQLite のバージョンが 3.35.0 より古い場合、dropColumn メソッドを使う前に Composer で doctrine/dbal パッケージをインストールする必要があります。このパッケージを使う場合、単一のマイグレーション内で複数のカラムを削除または変更することはサポートされていません。
#利用可能なコマンドエイリアス
Laravel は一般的なカラム削除に便利なメソッドをいくつか提供しています。以下の表にそれぞれのメソッドの説明を示します。
| Command | 説明 |
|---|---|
$table->dropMorphs('morphable'); |
morphable_id と morphable_type カラムを削除します。 |
$table->dropRememberToken(); |
remember_token カラムを削除します。 |
$table->dropSoftDeletes(); |
deleted_at カラムを削除します。 |
$table->dropSoftDeletesTz(); |
dropSoftDeletes() メソッドのエイリアスです。 |
$table->dropTimestamps(); |
created_at と updated_at カラムを削除します。 |
$table->dropTimestampsTz(); |
dropTimestamps() メソッドのエイリアスです。 |
#インデックス
#インデックスの作成
Laravel のスキーマビルダーは複数のインデックスタイプをサポートしています。以下の例では、新しい email カラムを作成し、その値がユニークであることを指定しています。インデックスを作成するには、カラム定義に unique メソッドをチェーンします。
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('users', function (Blueprint $table) {
$table->string('email')->unique();
});
または、カラム定義後にインデックスを作成することもできます。その場合は、スキーマビルダーのブループリントで unique メソッドを呼び出し、ユニークインデックスを付けたいカラム名を渡します。
$table->unique('email');
複数カラムの配列を渡すことで、複合インデックス(コンポジットインデックス)を作成できます。
$table->index(['account_id', 'created_at']);
インデックス作成時、Laravel はテーブル名、カラム名、インデックスタイプに基づいて自動的にインデックス名を生成しますが、第2引数で任意の名前を指定することも可能です。
$table->unique('email', 'unique_email');
#利用可能なインデックスタイプ
Laravel のスキーマビルダーブループリントクラスは、Laravel がサポートする各種インデックス作成メソッドを提供しています。各メソッドは第2引数にインデックス名を指定可能で、省略した場合はテーブル名、カラム名、インデックスタイプから自動生成されます。以下の表に各メソッドの説明を示します。
| Command | 説明 |
|---|---|
$table->primary('id'); |
プライマリキーを追加します。 |
$table->primary(['id', 'parent_id']); |
複合プライマリキーを追加します。 |
$table->unique('email'); |
ユニークインデックスを追加します。 |
$table->index('state'); |
通常のインデックスを追加します。 |
$table->fullText('body'); |
フルテキストインデックスを追加します(MySQL/PostgreSQL)。 |
$table->fullText('body')->language('english'); |
指定言語のフルテキストインデックスを追加します(PostgreSQL)。 |
$table->spatialIndex('location'); |
空間インデックスを追加します(SQLiteを除く)。 |
#インデックス長と MySQL / MariaDB
デフォルトで Laravel は utf8mb4 文字セットを使用します。MySQL 5.7.7 未満や MariaDB 10.2.2 未満のバージョンを使っている場合、マイグレーションで生成される文字列のデフォルト長を手動で設定しないとインデックスが作成できないことがあります。App\Providers\AppServiceProvider クラスの boot メソッド内で Schema::defaultStringLength メソッドを呼び出して設定できます。
use Illuminate\Support\Facades\Schema;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Schema::defaultStringLength(191);
}
または、データベースの innodb_large_prefix オプションを有効にする方法もあります。設定方法はデータベースのドキュメントを参照してください。
#インデックスのリネーム
インデックス名を変更するには、スキーマビルダーのブループリントが提供する renameIndex メソッドを使います。第1引数に現在のインデックス名、第2引数に新しい名前を指定します。
$table->renameIndex('from', 'to')
SQLite を使用している場合、renameIndex メソッドを使う前に Composer で doctrine/dbal パッケージをインストールする必要があります。
#インデックスの削除
インデックスを削除するには、インデックス名を指定する必要があります。Laravel はデフォルトでテーブル名、インデックス対象カラム名、インデックスタイプに基づいてインデックス名を自動生成します。以下は例です。
| Command | 説明 |
|---|---|
$table->dropPrimary('users_id_primary'); |
"users" テーブルのプライマリキーを削除します。 |
$table->dropUnique('users_email_unique'); |
"users" テーブルのユニークインデックスを削除します。 |
$table->dropIndex('geo_state_index'); |
"geo" テーブルの通常インデックスを削除します。 |
$table->dropFullText('posts_body_fulltext'); |
"posts" テーブルのフルテキストインデックスを削除します。 |
$table->dropSpatialIndex('geo_location_spatialindex'); |
"geo" テーブルの空間インデックスを削除します(SQLiteを除く)。 |
インデックス削除メソッドにカラム名の配列を渡すと、テーブル名、カラム、インデックスタイプに基づいた慣例的なインデックス名が生成されます。
Schema::table('geo', function (Blueprint $table) {
$table->dropIndex(['state']); // 'geo_state_index' インデックスを削除
});
#外部キー制約
Laravel は外部キー制約の作成もサポートしており、データベースレベルで参照整合性を強制できます。例えば、posts テーブルに user_id カラムを定義し、users テーブルの id カラムを参照する場合は以下のようにします。
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('posts', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
この構文は冗長なので、Laravel は慣例を利用してより簡潔に書けるメソッドを提供しています。foreignId メソッドを使うと、上記の例は以下のように書き換えられます。
Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
});
foreignId メソッドは UNSIGNED BIGINT 相当のカラムを作成し、constrained メソッドは慣例に基づいて参照先のテーブルとカラムを決定します。テーブル名が慣例と異なる場合は、constrained メソッドに手動で指定できます。また、生成されるインデックス名も指定可能です。
Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')->constrained(
table: 'users', indexName: 'posts_user_id'
);
});
外部キー制約の "on delete" と "on update" の動作も指定できます。
$table->foreignId('user_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');
これらの動作には、より表現的なメソッドも用意されています。
| メソッド | 説明 |
|---|---|
$table->cascadeOnUpdate(); |
更新時にカスケードします。 |
$table->restrictOnUpdate(); |
更新時に制限します。 |
$table->noActionOnUpdate(); |
更新時に何もしません。 |
$table->cascadeOnDelete(); |
削除時にカスケードします。 |
$table->restrictOnDelete(); |
削除時に制限します。 |
$table->nullOnDelete(); |
削除時に外部キー値を null に設定します。 |
追加の カラム修飾子 は constrained メソッドの前に呼び出す必要があります。
$table->foreignId('user_id')
->nullable()
->constrained();
#外部キーの削除
外部キーを削除するには、dropForeign メソッドを使い、削除したい外部キー制約名を渡します。外部キー制約名はインデックスと同じ命名規則で、テーブル名とカラム名に "_foreign" を付けたものです。
$table->dropForeign('posts_user_id_foreign');
または、外部キーを持つカラム名の配列を dropForeign メソッドに渡すこともできます。この配列は Laravel の命名規則に基づいて外部キー制約名に変換されます。
$table->dropForeign(['user_id']);
#外部キー制約の有効・無効切り替え
マイグレーション内で外部キー制約を有効または無効にするには、以下のメソッドを使います。
Schema::enableForeignKeyConstraints();
Schema::disableForeignKeyConstraints();
Schema::withoutForeignKeyConstraints(function () {
// このクロージャ内では制約が無効になります...
});
SQLite はデフォルトで外部キー制約を無効にしています。SQLite を使う場合は、マイグレーションで外部キーを作成する前にデータベース設定で 外部キーサポートを有効にする 必要があります。また、SQLite はテーブル作成時のみ外部キーをサポートし、テーブル変更時にはサポートしません。
#イベント
利便性のため、各マイグレーション操作は イベント を発行します。以下のイベントはすべて基底クラス Illuminate\Database\Events\MigrationEvent を継承しています。
| クラス | 説明 |
|---|
| Illuminate\Database\Events\MigrationsStarted | マイグレーションのバッチ実行が開始される直前に発行されます。 |
| Illuminate\Database\Events\MigrationsEnded | マイグレーションのバッチ実行が終了した直後に発行されます。 |
| Illuminate\Database\Events\MigrationStarted | 単一のマイグレーション実行が開始される直前に発行されます。 |
| Illuminate\Database\Events\MigrationEnded | 単一のマイグレーション実行が終了した直後に発行されます。 |
| Illuminate\Database\Events\SchemaDumped | データベーススキーマのダンプが完了したときに発行されます。 |
| Illuminate\Database\Events\SchemaLoaded | 既存のデータベーススキーマダンプが読み込まれたときに発行されます。 |