データベース: マイグレーション
はじめに
マイグレーションは、データ ベースのためのバージョン管理のようなものであり、チームがアプリケーションのデータベーススキーマ定義を定義して共有できるようにします。ソースコントロールから変更をプルした後にチームメイトに手動でローカルデータベーススキーマに列を追加するように指示する必要があったことがある場合、データベースマイグレーションが解決する問題に直面しています。
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);