Depois de algumas tentativas de solução excessivamente projetadas e inteligentes, acho que o seguinte é uma solução viável para o problema.
tl; dr:
- Migrações de Bookend em ambos os lados das migrações que criam o esquema do nada.
- Atualizar projeto.
- Migre.
- Exclua os bookends e todas as migrações anteriores.
- Excluir registros de
migrations
tabela.
O primeiro bookend renomeia as tabelas afetadas. O segundo bookend copia os dados das tabelas renomeadas para as tabelas novas e, em seguida, exclui as tabelas renomeadas.
Observação:você pode fazer o que quiser dentro dos suportes para livros, isso é apenas o mínimo.
Então, digamos que você tenha algo como o seguinte para migrações:
- 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
Criaríamos outra migração:
- 2017_09_05_000004_pre_refresh.php
Criaríamos outra migração com base no conhecimento que temos agora:
- 2017_09_05_000005_create_some_table.php
Criaríamos o último bookend, onde ocorrerá a migração de dados:
- 2017_09_05_000006_post_refresh.php
As primeiras quatro migrações não serão executadas porque já foram.
/** 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);
}
}
}
Não há necessidade de um down, porque este é um negócio de um tiro. Isso será executado primeiro, o que deve resultar na renomeação de todas as tabelas listadas na matriz. Em seguida, as migrações consolidadas (otimizadas) serão executadas.
/** 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');
}
}
}
Depois de executar isso, você pode excluir todas as suas migrações do
pre_refresh
e anterior. Assim como o post_refresh
. Então você pode ir para as migrations
table e exclua as entradas para essas migrações. A exclusão das entradas não é totalmente necessária, mas se você
migrate:rollback
você receberá mensagens de erro informando que a migração não pode ser encontrada. Advertências
- Se a arquitetura não for modular por design, pode ser bastante complicada. No entanto, se você separou seu código em serviços, parece ser um pouco mais fácil.
- O tratamento de erros do Laravel e as mensagens durante as migrações são muito limitados; portanto, a depuração pode ser difícil.
- Recomendamos começar com as tabelas mais estáveis em seu aplicativo/serviço. Além disso, começar com aqueles que são fundamentais para seu aplicativo também pode ser benéfico.
Nota:Quando eu realmente fizer isso em produção, não apenas no meu local (repetidamente), e se não houver uma resposta melhor, aceitarei isso.
Considerações
Se você estiver dividindo seu aplicativo em provedores de serviços com migrações discretas, poderá comentar o provedor de serviços em
/config/app
quando você executa as migrações. Dessa forma, você cria um lote para o serviço agora com linha de base. Então, digamos que você tenha as seguintes migrações, onde cada letra representa uma migração e cada letra duplicada representa o mesmo serviço:- A
- B
- C
- A
- C
- B
- A
Após consolidar o serviço A:
- B
- C
- C
- B
- A
Após consolidar B:
- C
- C
- A
- B
Após consolidar C:
- A
- B
- C
atualizar
54 migrações para 27 até agora. Eu até tirei algumas alterações de esquema de grandes
up()
e down()
métodos e torná-los migrações separadas. O bom efeito colateral aqui são os lotes. Eu migrei começando com as tabelas base nas quais todo o resto é suportado; portanto, reverter é mais serviço por serviço.