過度に設計され、過度に巧妙な解決策を2回試みた後、次のことが問題の実行可能な解決策だと思います。
tl; dr:
- 何もないところからスキーマを構築する移行のいずれかの側でのブックエンド移行。
- プロジェクトを更新します。
- 移行します。
- ブックエンドと以前のすべての移行を削除します。
migrations
からレコードを削除します テーブル。
最初のブックエンドは、影響を受けるテーブルの名前を変更します。 2番目のブックエンドは、名前が変更されたテーブルから新しいテーブルにデータをコピーしてから、名前が変更されたテーブルを削除します。
注:ブックエンド内で好きなことを行うことができます。これは最小限のことです。
したがって、移行について次のようなものを考えてみましょう。
- 2017_09_05_000000_create_some_table.php
- 2017_09_05_000001_add_field_x_to_some_table.php
- 2017_09_05_000002_add_field_y_to_some_table.php
- 2017_09_05_000003_add_field_z_to_some_table.php
別の移行を作成します:
- 2017_09_05_000004_pre_refresh.php
現在の知識に基づいて、別の移行を作成します:
- 2017_09_05_000005_create_some_table.php
データ移行が行われる最後のブックエンドを作成します:
- 2017_09_05_000006_post_refresh.php
最初の4つの移行はすでに実行されているため、実行されません。
/** 2017_09_05_000004_pre_refresh.php */
class PreRefresh extends Migration
{
public function up()
{
$prefix = 'zz_';
$tablesToRename = [
'foos',
'bars'
];
foreach($tablesToRename as $table) {
Schema::rename($table, $prefix . $table);
}
}
}
これはワンショット取引であるため、ダウンの必要はありません。これが最初に実行され、配列にリストされているすべてのテーブルの名前が変更されます。次に、統合された(最適化された)移行が実行されます。
/** 2017_09_05_000006_post_refresh.php */
class PostRefresh extends Migration
{
public function up()
{
// Do what you need to do.
// If you cannot use your models, just use DB::table() commands.
$foos = DB::table('zz_foos')->get();
foreach ($foos as $foo) {
DB::table('foo')->insert([
'id' => $foo->id,
'created_at' => $foo->created_at,
'updated_at' => $foo->updated_at
]);
}
$bars = DB::table('zz_bars')->get();
foreach ($bars as $bar) {
DB::table('bar')->insert([
'id' => $bar->id,
'created_at' => $bar->created_at,
'updated_at' => $bar->updated_at,
'foo_id' => $bar->foo_id
]);
}
// Tear down.
$prefix = 'zz_';
$tablesToRename = [
'foo',
'bar'
];
foreach ($tablesToRename as $table) {
DB::statement('SET FOREIGN_KEY_CHECKS=0');
Schema::dropIfExists($prefix . $table);
DB::statement('SET FOREIGN_KEY_CHECKS=1');
}
}
}
これを実行した後、pre_refresh
からすべての移行を削除できます および以前。 post_refresh
と同様に 。次に、migrations
に進むことができます テーブルを作成し、それらの移行のエントリを削除します。
エントリを削除する必要はありませんが、migrate:rollback
を実行する場合 移行が見つからないことを示すエラーメッセージが表示されます。
警告
- アーキテクチャが設計上モジュール化されていない場合、非常に面倒になる可能性があります。ただし、コードをサービスに分割している場合は、少し簡単に見えます。
- 移行中のLaravelエラー処理とメッセージは非常に限られています。そのため、デバッグが困難になる可能性があります。
- アプリ/サービスで最も安定したテーブルから始めることを強くお勧めします。さらに、アプリの基礎となるものから始めることも有益であることがわかるかもしれません。
注:私が実際にこれを本番環境で行う場合、ローカルだけでなく(何度も何度も)、より良い答えがない場合は、これを受け入れます。
考慮事項
慎重に移行してアプリケーションをサービスプロバイダーに分割する場合は、/config/app
でサービスプロバイダーをコメントアウトできます。 移行を実行するとき。このようにして、現在ベースライン化されているサービスのバッチを作成します。したがって、次の移行があり、各文字が移行を表し、重複する各文字が同じサービスを表すとします。
- A
- B
- C
- A
- C
- B
- A
サービスAを統合した後:
- B
- C
- C
- B
- A
Bを統合した後:
- C
- C
- A
- B
Cを統合した後:
- A
- B
- C
更新
これまでに54回の移行が27回に減少しました。大きなup()
からいくつかのスキーマの変更を引き出しました およびdown()
メソッドを作成し、それらを個別に移行します。ここでの素晴らしい副作用はバッチです。他のすべてがサポートされているベーステーブルから移行しました。したがって、ロールバックはサービスごとにより多くのサービスを提供します。