Setelah beberapa upaya solusi yang terlalu direkayasa dan terlalu pintar, menurut saya berikut ini adalah solusi yang bisa diterapkan untuk masalah tersebut.
tl; dr:
- Migrasi akhir buku di kedua sisi migrasi yang membangun skema dari nol.
- Perbarui proyek.
- Bermigrasi.
- Hapus akhir buku dan semua migrasi sebelumnya.
- Hapus catatan dari
migrations
meja.
Bookend pertama mengganti nama tabel yang terpengaruh. Bookend kedua menyalin data dari tabel yang diganti namanya ke tabel baru, lalu menghapus tabel yang diganti namanya.
Catatan:Anda dapat melakukan apapun yang Anda suka di dalam buku, ini hanya minimum.
Jadi, katakanlah Anda sesuatu seperti berikut untuk migrasi:
- 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
Kami akan membuat migrasi lain:
- 2017_09_05_000004_pre_refresh.php
Kami akan membuat migrasi lain berdasarkan pengetahuan yang kami miliki sekarang:
- 2017_09_05_000005_create_some_table.php
Kami akan membuat bookend terakhir, di mana migrasi data akan terjadi:
- 2017_09_05_000006_post_refresh.php
Empat migrasi pertama tidak akan dijalankan karena sudah dijalankan.
/** 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);
}
}
}
Tidak perlu turun, karena ini adalah kesepakatan satu tembakan. Ini akan dijalankan terlebih dahulu, yang akan mengakibatkan semua tabel yang terdaftar dalam array diganti namanya. Kemudian migrasi gabungan (dioptimalkan) akan berjalan.
/** 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');
}
}
}
Setelah menjalankan ini, Anda dapat menghapus semua migrasi Anda dari pre_refresh
dan sebelumnya. Serta post_refresh
. Kemudian Anda dapat menuju ke migrations
tabel dan hapus entri untuk migrasi tersebut.
Menghapus entri tidak sepenuhnya diperlukan, tetapi jika Anda migrate:rollback
Anda akan mendapatkan pesan kesalahan yang menyatakan bahwa migrasi tidak dapat ditemukan.
Peringatan
- Jika arsitekturnya tidak dirancang secara modular, itu bisa sangat merepotkan. Namun, jika Anda telah memisahkan kode ke dalam layanan, tampaknya akan sedikit lebih mudah.
- Penanganan kesalahan Laravel dan pesan selama migrasi sangat terbatas; jadi, debugging bisa jadi sulit.
- Sangat disarankan untuk memulai dengan tabel paling stabil di aplikasi/layanan Anda. Selanjutnya, memulai dengan hal-hal yang mendasar untuk aplikasi Anda mungkin juga terbukti bermanfaat.
Catatan:Ketika saya benar-benar melakukan ini dalam produksi, bukan hanya lokal saya (berulang kali), dan jika tidak ada jawaban yang lebih baik, maka saya akan menerimanya.
Pertimbangan
Jika Anda memecah aplikasi menjadi penyedia layanan dengan migrasi rahasia, Anda dapat mengomentari penyedia layanan di /config/app
saat Anda menjalankan migrasi. Dengan cara ini Anda membuat kumpulan untuk layanan yang sekarang menjadi dasar. Jadi, katakanlah Anda memiliki migrasi berikut di mana setiap huruf mewakili migrasi, dan setiap huruf duplikat mewakili layanan yang sama:
- A
- B
- C
- A
- C
- B
- A
Setelah mengkonsolidasikan layanan A:
- B
- C
- C
- B
- A
Setelah mengkonsolidasikan B:
- C
- C
- A
- B
Setelah mengkonsolidasikan C:
- A
- B
- C
perbarui
54 migrasi turun menjadi 27 sejauh ini. Saya bahkan mengeluarkan beberapa perubahan Skema dari up()
besar dan down()
metode dan membuat mereka migrasi terpisah. Efek samping yang bagus di sini adalah batch. Saya bermigrasi mulai dengan tabel dasar yang mendukung segala hal lainnya; oleh karena itu, memutar kembali adalah lebih banyak layanan demi layanan.