データベース: マイグレーション
はじめに
マイグレーションは、データ ベースのためのバージョン管理のようなものであり、チームがアプリケーションのデータベーススキーマ定義を定義して共有できるようにします。ソースコントロールから変更をプルした後にチームメイトに手動でローカルデータベーススキーマに列を追加するように指示する必要があったことがある場合、データベースマイグレーションが解決する問題に直面しています。
LaravelのSchema ファサード は、Laravelがサポートするすべてのデータベースシステムでテーブルの作成や操作をサポートするためのデータベースに依存しないサポートを提供します。通常、マイグレーションはこのファサードを使用してデータベースのテーブルやカラムを作成および変更します。
マイグレーションの生成
make:migration Artisanコマンド を使用してデータベースマイグレーションを生成することができます。新しいマイグレーションは database/migrations ディレクトリに配置されます。各マイグレーションのファイル名には、Laravelがマイグレーションの順序を決定するためのタイムスタンプが含まれています:
php artisan make:migration create_flights_table
Laravelはマイグレーションの名前を使用して、テーブルの名前やマイグレーションが新しいテーブルを作成するかどうかを推測しようとします。Laravelがマイグレーション名からテーブル名を決定できる場合、Laravelは生成されたマイグレーションファイルに指定されたテーブルを自動的に入力します。それ以外の場合は、マイグレーションファイルでテーブルを手動で指定することができます。
make:migration コマンドを実行する際に --path オプションを使用して生成されるマイグレーションのカスタムパスを指定することができます。指定されたパスは、アプリケーションのベースパスを基準として相対的である必要があります。
マイグレーションスタブは、スタブの公開を使用してカスタマイズすることができます。
マイグレーションのスクワッシュ
アプリケーションを構築するにつれて、時間の経過とともにますます多くのマイグレーションが蓄積されることがあります。これにより、database/migrations ディレクトリが数百ものマイグレーションで肥大化する可能性があります。必要であれば、マイグレーションを1つの SQL ファイルに「スクワッシュ」することができます。開始するには、schema:dump コマンドを実行してください:
php artisan schema:dump
# Dump the current database schema and prune all existing migrations...
php artisan schema:dump --prune
このコマンドを実行すると、Laravel はアプリケーションの database/schema ディレクトリに「スキーマ」ファイルを書き込みます。スキーマファイルの名前は、使用しているデータベース接続に対応します。これで、データベースをマイグレーションしようとするときに、他に実行されたマイグレーションがない場合、Laravel は最初に使用しているデータベース接続のスキーマファイルの SQL ステートメントを実行します。スキーマファイルの SQL ステートメントを実行した後、Laravel はスキーマダンプに含まれていなかった残りのマイグレーションを実行します。
アプリケーションのテストが、ローカル開発中に通常使用するものとは異なるデータベース接続を使用している場合、テストがデータベースを構築できるように、そのデータベース接続をダンプしていることを確認する必要があります。通常の開発中に使用するデータベース接続をダンプした後に、これを行うことをお勧めします:
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
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('flights', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('airline');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::drop('flights');
}
};
マイグレーション接続の設定
マイグレーションが、アプリケーションのデフォルトのデータベース接続以外のデータベース接続とやり取りする場合は、マイグレーションの $connection プロパティを設定する必要があります:
/**
* The database connection that should be used by the migration.
*
* @var string
*/
protected $connection = 'pgsql';
/**
* Run the migrations.
*/
public function up(): void
{
// ...
}
マイグレーションの実行
未解決のすべてのマイグレーションを実行するには、migrate Artisan コマンドを実行します:
php artisan migrate
これまでに実行されたマイグレーションを確認したい場合は、migrate:status Artisan コマンドを使用できます:
php artisan migrate:status
実際に実行されるマイグレーションの SQL ステートメントを確認したい場合は、migrate コマンドに --pretend フラグを指定できます:
php artisan migrate --pretend
マイグレーションの実行を分離する
アプリケーションを複数のサーバーに展開し、マイグレーションを展開プロセスの一部として実行している場合、おそらく2つのサーバーが同時にデータベースをマイグレーションしようとすることは避けたいでしょう。これを避けるために、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
1 つのコマンドを使用してロールバックとマイグレーション
migrate:refreshコマンドは、すべてのマイグレーションをロールバックしてからmigrateコマンドを実行します。このコマンドは、実質的にデータベース全体を再作成します:
php artisan migrate:refresh
# Refresh the database and run all database seeds...
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つの引数を受け入れます。最初の引数はテーブルの名前であり、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、hasIndexメソッドを使用して、テーブル、カラム、またはインデックスの存在を判定できます:
if (Schema::hasTable('users')) {
// The "users" table exists...
}
if (Schema::hasColumn('users', 'email')) {
// The "users" table exists and has an "email" column...
}
if (Schema::hasIndex('users', ['email'], 'unique')) {
// The "users" table exists and has a unique index on the "email" column...
}
データベース接続とテーブルオプション
データベース接続に対してスキーマ操作を実行する場合、アプリケーションのデフォルト接続でない接続を使用するには、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 と PostgreSQL でのみサポートされています:
Schema::create('calculations', function (Blueprint $table) {
$table->comment('Business calculations');
// ...
});
テーブルの更新
Schema ファサードの table メソッドを使用して既存のテーブルを更新できます。create メソッドと同様に、table メソッドは、テーブルの名前と、列やインデックスを追加するために使用できる Blueprint インスタンスを受け取るクロージャを受け入れます:
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');
外部キーを持つテーブルの名前変更
テーブルの名前を変更する前に、マイグレーションファイルでテーブルに対する外部キー制約が暗黙の名前ではなく明示的な名前を持つことを確認する必要があります。そうしないと、外部キー制約の名前は古いテーブル名を参照します。
カラム
カラムの作成
Schema ファサードの table メソッドを使用して既存のテーブルを更新できます。create メソッドと同様に、table メソッドはテーブルの名前と、テーブルにカラムを追加するために使用できる Illuminate\Database\Schema\Blueprint インスタンスを受け取るクロージャを引数として受け入れます:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('users', function (Blueprint $table) {
$table->integer('votes');
});
利用可能なカラムタイプ
スキーマビルダーのブループリントには、データベーステーブルに追加できるさまざまなタイプのカラムに対応するメソッドが用意されています。利用可能な各メソッドは以下の表にリストされています:
bigIncrements bigInteger binary boolean char dateTimeTz dateTime date decimal double enum float foreignId foreignIdFor foreignUlid foreignUuid geography geometry id increments integer ipAddress json jsonb longText macAddress mediumIncrements mediumInteger mediumText morphs nullableMorphs nullableTimestamps nullableUlidMorphs nullableUuidMorphs rememberToken set smallIncrements smallInteger softDeletesTz softDeletes string text timeTz time timestampTz timestamp timestampsTz timestamps tinyIncrements tinyInteger tinyText unsignedBigInteger unsignedInteger unsignedMediumInteger unsignedSmallInteger unsignedTinyInteger ulidMorphs uuidMorphs ulid uuid year
bigIncrements()
bigIncrements メソッドは、自動インクリメントの UNSIGNED BIGINT(主キー)と同等の列を作成します:
$table->bigIncrements('id');
bigInteger()
bigInteger メソッドは、BIGINT と同等の列を作成します:
$table->bigInteger('votes');
binary()
binary メソッドは、BLOB と同等の列を作成します:
$table->binary('photo');
MySQL、MariaDB、または SQL Server を利用する場合、length と fixed 引数を渡すことで、VARBINARY または BINARY と同等の列を作成できます:
$table->binary('data', length: 16); // VARBINARY(16)
$table->binary('data', length: 16, fixed: true); // BINARY(16)
boolean()
boolean メソッドは、BOOLEAN と同等の列を作成します:
$table->boolean('confirmed');
char()
char メソッドは、指定された長さの CHAR と同等の列を作成します:
$table->char('name', length: 100);
dateTimeTz()
dateTimeTz メソッドは、オプションの小数秒精度を持つ DATETIME(タイムゾーン付き)と同等の列を作成します:
$table->dateTimeTz('created_at', precision: 0);
dateTime()
dateTime メソッドは、オプションの小数秒精度を持つ DATETIME と同等の列を作成します:
$table->dateTime('created_at', precision: 0);
date()
date メソッドは、DATE と同等の列を作成します:
$table->date('created_at');
decimal()
decimal メソッドは、指定された精度(総桁数)とスケール(小数桁数)を持つ DECIMAL と同等の列を作成します:
$table->decimal('amount', total: 8, places: 2);
double()
double メソッドは、DOUBLE と同等の列を作成します:
$table->double('amount');
enum()
enum メソッドは、指定された有効な値を持つ ENUM と同等の列を作成します:
$table->enum('difficulty', ['easy', 'hard']);
float()
floatメソッドは、指定された精度でFLOATと同等の列を作成します。
$table->float('amount', precision: 53);
foreignId()
foreignIdメソッドは、UNSIGNED BIGINTと同等の列を作成します。
$table->foreignId('user_id');
foreignIdFor()
foreignIdForメソッドは、指定されたモデルクラスのために{column}_idと同等の列を追加します。列のタイプは、モデルキーのタイプに応じてUNSIGNED BIGINT、CHAR(36)、またはCHAR(26)になります。
$table->foreignIdFor(User::class);
foreignUlid()
foreignUlidメソッドは、ULIDと同等の列を作成します。
$table->foreignUlid('user_id');
foreignUuid()
foreignUuidメソッドは、UUIDと同等の列を作成します。
$table->foreignUuid('user_id');
geography()
geographyメソッドは、指定された空間タイプとSRID(空間参照システム識別子)でGEOGRAPHYと同等の列を作成します。
$table->geography('coordinates', subtype: 'point', srid: 4326);
空間タイプのサポートは、データベースドライバに依存します。データベースのドキュメントを参照してください。アプリケーションがPostgreSQLデータベースを利用している場合、geographyメソッドを使用する前にPostGIS拡張機能をインストールする必要があります。
geometry()
geometryメソッ ドは、指定された空間タイプとSRID(空間参照システム識別子)でGEOMETRYと同等の列を作成します。
$table->geometry('positions', subtype: 'point', srid: 0);
空間タイプのサポートは、データベースドライバに依存します。データベースのドキュメントを参照してください。アプリケーションがPostgreSQLデータベースを利用している場合、geometryメソッドを使用する前にPostGIS拡張機能をインストールする必要があります。
idメソッドはbigIncrementsメソッドのエイリアスです。デフォルトでは、このメソッドはid列を作成しますが、別の名前を列に割り当てたい場合は、列名を渡すことができます:
$table->id();
increments()
incrementsメソッドは、自動増分のUNSIGNED INTEGERと同等の列を主キーとして作成します:
$table->increments('id');
integer()
integerメソッドはINTEGERと同等の列を作成します:
$table->integer('votes');
ipAddress()
ipAddressメソッドはVARCHARと同等の列を作成します:
$table->ipAddress('visitor');
When using PostgreSQL, an `INET` column will be created.
json()
jsonメソッドはJSONと同等の列を作成します:
$table->json('options');
jsonb()
jsonbメソッドはJSONBと同等の列を作成します:
$table->jsonb('options');
longText()
longTextメソッドはLONGTEXTと同等の列を作成します:
$table->longText('description');
MySQLまたはMariaDBを使用する場合、LONGBLOBと同等の列を作成するために、列にbinary文字セットを適用することができます:
$table->longText('data')->charset('binary'); // LONGBLOB
macAddress()
macAddressメソッドはMACアドレスを保持するために意図された列を作成します。PostgreSQLなど一部のデータベースシステムには、このタイプのデータ用の専用の列タイプがあります。他のデータベースシステムでは、文字列と同等の列が使用されます:
$table->macAddress('device');
mediumIncrements()
mediumIncrementsメソッドは、自動増分のUNSIGNED MEDIUMINTと同等の列を主キーとして作成します:
$table->mediumIncrements('id');
mediumInteger()
$table->mediumInteger('votes');
mediumText()
mediumTextメソッドはMEDIUMTEXTに相当するカラムを作成します:
$table->mediumText('description');
MySQLまたはMariaDBを利用する場合、MEDIUMBLOBに相当するカラムを作成するためにカラムにbinary文字セットを適用することができます:
$table->mediumText('data')->charset('binary'); // MEDIUMBLOB
morphs()
morphsメソッドは、{column}_idに相当するカラムと{column}_typeに相当するVARCHARカラムを追加する便利なメソッドです。{column}_idのカラムタイプは、モデルキーのタイプに応じてUNSIGNED BIGINT、CHAR(36)、またはCHAR(26)になります。
このメソッドは、多態性のEloquentリレーションシップに必要なカラムを定義する際に使用されることを意図しています。次の例では、taggable_idとtaggable_typeのカラムが作成されます:
$table->morphs('taggable');
nullableTimestamps()
nullableTimestampsメソッドは、timestampsメソッ ドのエイリアスです:
$table->nullableTimestamps(precision: 0);
nullableMorphs()
このメソッドはmorphsメソッドと似ていますが、作成されるカラムは「nullable」になります:
$table->nullableMorphs('taggable');
nullableUlidMorphs()
このメソッドはulidMorphsメソッドと似ていますが、作成されるカラムは「nullable」になります:
$table->nullableUlidMorphs('taggable');
nullableUuidMorphs()
このメソッドはuuidMorphsメソッドと似ていますが、作成されるカラムは「nullable」になります:
$table->nullableUuidMorphs('taggable');
rememberToken()
rememberTokenメソッドは、現在の「remember me」認証トークンを格納するために意図されたnullableなVARCHAR(100)に相当するカラムを作成します:
$table->rememberToken();
set()
setメソッドは、指定された有効な値のリストでSET相当のカラムを作成します。
$table->set('flavors', ['strawberry', 'vanilla']);
smallIncrements()
smallIncrementsメソッドは、プライマリキーとしてのUNSIGNED SMALLINT相当の自動増分カラムを作成します。
$table->smallIncrements('id');
smallInteger()
smallIntegerメソッドは、SMALLINT相当のカラムを作成します。
$table->smallInteger('votes');
softDeletesTz()
softDeletesTzメソッドは、オプションの小数秒精度を持つ、削除されたdeleted_at TIMESTAMP(タイムゾーン付き)相当のカラムを追加します。このカラムは、Eloquentの「ソフトデリート」機能に必要なdeleted_atタイムスタンプを保存するために使用されます。
$table->softDeletesTz('deleted_at', precision: 0);
softDeletes()
softDeletesメソッドは、オプションの小数秒精度を持つ、削除されたdeleted_at TIMESTAMP相当のカラムを追加します。このカラムは、Eloquentの「ソフトデリート」機能に必要なdeleted_atタイムスタンプを保存するために使用されます。
$table->softDeletes('deleted_at', precision: 0);
string()
stringメソッドは、指定された長さのVARCHAR相当のカラムを作成します。
$table->string('name', length: 100);