Po několika přetechnizovaných a příliš chytrých pokusech o řešení si myslím, že následující je funkční řešení problému.
tl;dr:
- Migrace na obou stranách migrace, které vytvářejí schéma z ničeho.
- Aktualizujte projekt.
- Migrovat.
- Smažte zarážky a všechny předchozí migrace.
- Odstraňte záznamy z
migrations
stůl.
První bookend přejmenuje postižené tabulky. Druhá zarážka zkopíruje data z přejmenovaných tabulek do nových tabulek a poté přejmenované tabulky odstraní.
Poznámka:Uvnitř zarážek na knihy si můžete dělat, co chcete, je to jen minimum.
Řekněme tedy něco jako následující pro migrace:
- 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
Vytvořili bychom další migraci:
- 2017_09_05_000004_pre_refresh.php
Vytvořili bychom další migraci na základě znalostí, které nyní máme:
- 2017_09_05_000005_create_some_table.php
Vytvořili bychom poslední bookend, kde dojde k migraci dat:
- 2017_09_05_000006_post_refresh.php
První čtyři migrace nebudou spuštěny, protože již byly.
/** 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);
}
}
}
Není potřeba down, protože tohle je jednorázový obchod. To se spustí jako první, což by mělo vést k přejmenování všech tabulek uvedených v poli. Poté se spustí konsolidovaná (optimalizovaná) migrace.
/** 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');
}
}
}
Po spuštění můžete odstranit všechny své migrace z pre_refresh
a předchozí. Stejně jako post_refresh
. Poté se můžete vydat do migrations
a odstraňte položky pro tyto migrace.
Odstranění položek není úplně nutné, ale pokud migrate:rollback
zobrazí se chybové zprávy, že migraci nelze nalézt.
Upozornění
- Pokud architektura není svým designem modulární, může být značně těžkopádná. Pokud jste však svůj kód rozdělili do služeb, zdá se to být o něco jednodušší.
- Zpracování chyb Laravel a zpráv během migrace jsou velmi omezené; takže ladění může být obtížné.
- Důrazně doporučujeme začít s nejstabilnějšími tabulkami ve vaší aplikaci/službě. Dále může být užitečné začít s těmi, které jsou základem vaší aplikace.
Poznámka:Když to skutečně udělám ve výrobě, nejen v místním (znovu a znovu), a pokud neexistuje lepší odpověď, přijmu to.
Úvahy
Pokud svou aplikaci rozdělujete na poskytovatele služeb pomocí diskrétních migrací, můžete poskytovatele služeb komentovat v /config/app
když spustíte migraci. Tímto způsobem vytvoříte dávku pro nyní základní službu. Řekněme tedy, že máte následující migrace, kde každé písmeno představuje migraci a každé duplicitní písmeno představuje stejnou službu:
- A
- B
- C
- A
- C
- B
- A
Po konsolidaci služby A:
- B
- C
- C
- B
- A
Po konsolidaci B:
- C
- C
- A
- B
Po konsolidaci C:
- A
- B
- C
aktualizovat
54 migrací kleslo na 27 zatím. Dokonce jsem vytáhl některé změny schématu z velkého up()
a down()
a provést z nich samostatné migrace. Příjemným vedlejším účinkem jsou dávky. Provedl jsem migraci počínaje základními tabulkami, na kterých je podporováno vše ostatní; proto je vrácení zpět více službou od služby.