След няколко прекомерно проектирани и прекалено умни опита за решение, мисля, че следното е работещо решение на проблема.
tl;dr:
- Миграции на Bookend от двете страни на миграцията(ите), които изграждат схемата от нищото.
- Актуализиране на проекта.
- Мигриране.
- Изтрийте подложките за книги и всички предишни миграции.
- Изтриване на записи от
migrations
маса.
Първият подложка за книги преименува засегнатите таблици. Вторият разделител за книги копира данните от преименуваните таблици в новите таблици, след което изтрива преименуваните таблици.
Забележка:Можете да правите каквото искате в подложките за книги, това е само минимум.
Така че, нека ви кажем нещо като следното за миграции:
- 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
Първите четири миграции няма да се изпълняват, защото вече са били.
/** 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
когато стартирате миграциите. По този начин създавате партида за вече базовата услуга. Така че, да приемем, че имате следните миграции, където всяка буква представлява миграция, а всяка дублирана буква представлява една и съща услуга:
- А
- Б
- C
- А
- C
- Б
- А
След консолидиране на услуга A:
- Б
- C
- C
- Б
- А
След консолидиране B:
- C
- C
- А
- Б
След консолидиране на C:
- А
- Б
- C
актуализация
54 миграции намаляват до 27 досега. Дори извадих някои промени в схемата от голям up()
и down()
методи и да ги направи отделни миграции. Приятният страничен ефект тук са партидите. Мигрирах, започвайки с базовите таблици, върху които се поддържа всичко останало; следователно връщането назад е повече услуга по услуга.