Efter et par overkonstruerede og alt for smarte løsningsforsøg, tror jeg, at følgende er en brugbar løsning på problemet.
tl;dr:
- Bogstøttemigreringer på begge sider af migration(er), der bygger skemaet fra ingenting.
- Opdater projekt.
- Migrer.
- Slet bogstøtter og alle tidligere migreringer.
- Slet poster fra
migrations
bord.
Den første bogstøtte omdøber de berørte tabeller. Den anden bogstøtte kopierer dataene fra de omdøbte tabeller til de nye tabeller og sletter derefter de omdøbte tabeller.
Bemærk:Du kan gøre, hvad du vil inde i bogstøtterne, dette er kun et minimum.
Så lad os sige, at du noget i stil med følgende for migreringer:
- 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 ville oprette endnu en migrering:
- 2017_09_05_000004_pre_refresh.php
Vi ville skabe endnu en migrering baseret på den viden, vi har nu:
- 2017_09_05_000005_create_some_table.php
Vi ville oprette den sidste bogstøtte, hvor datamigrering vil finde sted:
- 2017_09_05_000006_post_refresh.php
De første fire migreringer vil ikke blive kørt, fordi de allerede har været det.
/** 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);
}
}
}
Intet behov for et down, for dette er en one-shot aftale. Dette vil køre først, hvilket skulle resultere i, at alle tabellerne i arrayet omdøbes. Derefter vil de konsoliderede (optimerede) migrering(er) køre.
/** 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');
}
}
}
Efter at have kørt dette, kan du slette alle dine migreringer fra pre_refresh
og tidligere. Samt post_refresh
. Så kan du gå ind i migrations
tabel og slet posterne for disse migreringer.
Det er ikke helt nødvendigt at slette posterne, men hvis du migrate:rollback
du får fejlmeddelelser om, at migreringen ikke kan findes.
Forbehold
- Hvis arkitekturen ikke er modulopbygget, kan den være ret besværlig. Men hvis du har opdelt din kode i tjenester, ser det ud til at være lidt nemmere.
- Laravel fejlhåndtering og meddelelser under migreringer er meget begrænset; så fejlfinding kan være svært.
- Anbefales på det varmeste at starte med de mest stabile tabeller i din app/tjeneste. Derudover kan det også være en fordel at starte med dem, der er grundlæggende for din app.
Bemærk:Når jeg rent faktisk gør dette i produktionen, ikke kun min lokale (igen og igen), og hvis der ikke er et bedre svar, så vil jeg acceptere dette.
Overvejelser
Hvis du bryder din applikation ind til tjenesteudbydere med diskrete migreringer, så kan du kommentere tjenesteudbyderen i /config/app
når du kører migreringerne. På denne måde opretter du en batch til den nu baserede service. Så lad os sige, at du har følgende migreringer, hvor hvert bogstav repræsenterer en migrering, og hvert dubletbogstav repræsenterer den samme tjeneste:
- A
- B
- C
- A
- C
- B
- A
Efter konsolidering af tjeneste A:
- B
- C
- C
- B
- A
Efter konsolidering af B:
- C
- C
- A
- B
Efter konsolidering af C:
- A
- B
- C
opdatering
54 migrationer ned til 27 indtil videre. Jeg trak endda nogle skemaændringer ud fra store up()
og down()
metoder og gøre dem adskilte migrationer. Den gode bivirkning her er batchene. Jeg migrerede startende med basistabellerne, hvorpå alt andet er understøttet; derfor er tilbagerulning mere service for service.