Efter ett par överkonstruerade och alltför smarta lösningsförsök tror jag att följande är en fungerande lösning på problemet.
tl;dr:
- Bokstödsmigreringar på båda sidor av migrering(er) som bygger schemat från ingenting.
- Uppdatera projektet.
- Migrera.
- Ta bort bokstöd och alla tidigare migreringar.
- Ta bort poster från
migrations
tabell.
Det första bokstödet byter namn på de berörda tabellerna. Det andra bokstödet kopierar data från de omdöpta tabellerna till de nya tabellerna och tar sedan bort de omdöpta tabellerna.
Obs! Du kan göra vad du vill i bokstöden, detta är bara ett minimum.
Så låt oss säga att du har något i stil med följande för migrering:
- 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
Vi skulle skapa en annan migrering:
- 2017_09_05_000004_pre_refresh.php
Vi skulle skapa ytterligare en migrering baserat på den kunskap vi har nu:
- 2017_09_05_000005_create_some_table.php
Vi skulle skapa det sista bokstödet, där datamigrering kommer att ske:
- 2017_09_05_000006_post_refresh.php
De första fyra migreringarna kommer inte att köras eftersom de redan har gjorts.
/** 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);
}
}
}
Inget behov av ett dun, eftersom det här är en one-shot-affär. Detta kommer att köras först, vilket bör resultera i att alla tabeller som listas i arrayen byter namn. Sedan kommer den konsoliderade (optimerade) migreringen att köras.
/** 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');
}
}
}
När du har kört detta kan du ta bort alla dina migreringar från pre_refresh
och tidigare. Samt post_refresh
. Sedan kan du gå in i migrations
tabell och ta bort posterna för dessa migrering.
Att ta bort posterna är inte helt nödvändigt, men om du migrate:rollback
du kommer att få felmeddelanden om att migreringen inte kan hittas.
Varningar
- Om arkitekturen inte är modulär till sin design kan den vara ganska besvärlig. Men om du har delat upp din kod i tjänster verkar det vara lite enklare.
- Laravel-felhantering och meddelanden under migrering är mycket begränsad; så felsökning kan vara svårt.
- Rekommenderar starkt att börja med de mest stabila tabellerna i din app/tjänst. Dessutom kan det vara fördelaktigt att börja med de som är grundläggande för din app.
Obs:När jag faktiskt gör detta i produktionen, inte bara min lokala (om och om igen), och om det inte finns ett bättre svar, kommer jag att acceptera detta.
Överväganden
Om du bryter in din applikation till tjänsteleverantörer med diskreta migreringar kan du kommentera tjänsteleverantören i /config/app
när du kör migreringarna. På så sätt skapar du en batch för den nu baslinjebaserade tjänsten. Så låt oss säga att du har följande migreringar där varje bokstav representerar en migrering och varje dubblettbokstav representerar samma tjänst:
- A
- B
- C
- A
- C
- B
- A
Efter konsolidering av tjänst A:
- B
- C
- C
- B
- A
Efter konsolidering av B:
- C
- C
- A
- B
Efter konsolidering av C:
- A
- B
- C
uppdatering
54 migreringar ner till 27 hittills. Jag tog till och med ut några schemaändringar från stora up()
och down()
metoder och göra dem åtskilda migrationer. Den trevliga bieffekten här är satserna. Jag migrerade med början med bastabellerna där allt annat stöds; därför är återställning mer tjänst för tjänst.