mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-06 16:16:53 +01:00
314 lines
14 KiB
Plaintext
314 lines
14 KiB
Plaintext
Migração da Base de Dados
|
|
=========================
|
|
|
|
> Note|Nota: A função de migração de banco de dados está disponível desde a versão 1.1.6.
|
|
|
|
Como o código-fonte, a estrutura de um banco de dados está evoluindo conforme nós desenvolvemos e mantemos a aplicação. Por exemplo, durante o desenvolvimento, nós podemos querer adicionar uma nova tabela; ou depois de a apliação ser posta em produção, nós podemos nos dar conta da necessidade da adição de um índice em uma coluna. É importante manter o controle destas mudanças estruturais do banco de dados (chamadas **migrações**) da mesma maneira que fazemos com o código-fonte. Se o código-fonte e o banco de dados estão sem sincronia, é muito provável que o sistema como um todo pare de funcionar. Por esta razão, Yii fornece uma ferramenta de migração de banco de ddos que pode controlar o histórico de migrações do banco de dados, aplicar novas migrações ou reverter migrações existentes.
|
|
|
|
Os passos seguintes mostram como nós podemos usar a migração do banco de dados durante o desenvolvimento:
|
|
|
|
1. João cria uma nova migração (por exemplo, uma nova tabela)
|
|
2. João faz o commit da nova migração no sistem de versionamento de código-fonte (como SVN, GIT)
|
|
3. Pedro faz um update a partir do sistema de versionamento de código-fonte e recebe a nova migração
|
|
4. Pedro aplica a migração ao seu banco de dados local de desenvolvimento
|
|
|
|
|
|
Yii suporta migrações de banco de dados atraves da ferramenta de linha de comando `yiic migrate`. Esta ferramenta suporta a criação de novas migrações, a aplicação/reversão/reaplicação de migrações, e a exibição do histórico de migrações e as novas migrações.
|
|
|
|
A seguir, vamos descrever como usar esta ferramenta.
|
|
|
|
> Note|Nota: É melhor usar o yiic específico da aplicação (por exemplo, `cd caminho/até/protected`)
|
|
> quando trabalhar com o comando `migrate` ao invés de usar o do diretório `framework`.
|
|
> Certifique-se de que você tem um diretório `protected\migrations` e de que ele tem permissões de escrita.
|
|
> Verifique também se você configurou a conexão do banco de dados no seu arquivo `protected/config/console.php`.
|
|
|
|
Criando Migrações
|
|
-----------------
|
|
|
|
Para criar uma nova migração (por exemplo, criar uma nova tabela `news`), nós executamos o seguinte comando:
|
|
|
|
~~~
|
|
yiic migrate create <name>
|
|
~~~
|
|
|
|
O parâmetro obrigatório `name` especifica uma breve descrição da migração (por exemplo, `create_news_table`). Como nós vamos mostrar abaixo, o parâmetro `name` é usado como marte de uma classe PHP. Então, ele deve coter apenas letras, números e/ou caracteres de sublinhado.
|
|
|
|
~~~
|
|
yiic migrate create create_news_table
|
|
~~~
|
|
|
|
O comando acima vai criar, sob o diretório `protected/migrations` um novo arquivo chamado `m101129_185401_create_news_table.php`, que contém o seguinte código inicial:
|
|
|
|
~~~
|
|
[php]
|
|
class m101129_185401_create_news_table extends CDbMigration
|
|
{
|
|
public function up()
|
|
{
|
|
}
|
|
|
|
public function down()
|
|
{
|
|
echo "m101129_185401_create_news_table does not support migration down.\n";
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
// implement safeUp/safeDown instead if transaction is needed
|
|
public function safeUp()
|
|
{
|
|
}
|
|
|
|
public function safeDown()
|
|
{
|
|
}
|
|
*/
|
|
}
|
|
~~~
|
|
|
|
Note que o nome da classe é o mesmo que o nome do arquivo, o qual tem o padrão `m<timestamp>_<name>`, onde `<timestamp>` refere-se a um "carimbo de tempo" UTC (no formato `yymmdd_hhmmss`) de quando a migração é criada, e `<name>` é obtido a partir do parâmetro `name` da linha de comando.
|
|
|
|
O método `up()` deve conter o código implementando a migração de fato, enquanto o método `down()` pode conter o código revertendo o que é feito em `up()`.
|
|
|
|
Algumas vezes, é impossível implementar o método `down()`. Por exemplo, se nós removemos linhas de uma tabela em `up()`, nós não poderemos recuperá-las em `down()`. Neste caso, a migração é chamada irreversível, o que significa que nós não podemos reertê-la para um estado anterior do banco de dados. No código gerado acima, o método `down()` retorna `false` para indicar que a migração não pode ser revertida.
|
|
|
|
> Info|Informação: A partir da versão 1.1.7, se o método `up()` ou `down()` retornar
|
|
> `false`, todas as migrações seguintes serão canceladas. Anteriormente, na versão
|
|
> 1.1.6, o usuário teria que lançar exceções para cancelar as migrações seguintes.
|
|
|
|
Como um exemplo, vamos mostrar uma migração para a criação de uma tabela `news`.
|
|
|
|
~~~
|
|
[php]
|
|
class m101129_185401_create_news_table extends CDbMigration
|
|
{
|
|
public function up()
|
|
{
|
|
$this->createTable('tbl_news', array(
|
|
'id' => 'pk',
|
|
'title' => 'string NOT NULL',
|
|
'content' => 'text',
|
|
));
|
|
}
|
|
|
|
public function down()
|
|
{
|
|
$this->dropTable('tbl_news');
|
|
}
|
|
}
|
|
~~~
|
|
|
|
A classe base [CDbMigration] fornece um conjunto de métodos para a manupulação de dados e da estrutura de um banco de dados. Por exemplo, [CDbMigration::createTable] criará uma tabela, enquanto [CDbMigration::insert] vai inserir uma linha de dados. Todos estes métodos usam a conexão de banco de dados retornada por [CDbMigration::getDbConnection()], a qual por padrão retorna `Yii::app()->db`.
|
|
|
|
> Info|Informação: Você pode notar que os métodos de banco de dados fornecidos pela classe [CDbMigration] são muito similares aos em [CDbCommand]. De fato, eles são praticamente os mesmos, exceto que os métodos de [CDbMigration] vão medir o tempo usado e imprimir algumas mensagens sobre os parâmetros passados.
|
|
|
|
|
|
Migrações Transacionais
|
|
-----------------------
|
|
|
|
> Info|Informação: A funcionalidade de migrações transacionais é suportada desde a versão 1.1.7.
|
|
|
|
Ao realizar migrações complexas do banco de dados, nós geralmente queremos ter certeza de que cada migração teve sucesso ou de que ela falhou como um todo, para que o banco de dados mantenha a consistência e a integridade. Para alcançarmos este objetivo, nós podemos fazer uso das transações do banco de dados.
|
|
|
|
Nós podemos explicitamente iniciar uma transação do banco de dados e realizar o resto do código relacionado ao banco de dados dentro da transação, como a seguir:
|
|
|
|
~~~
|
|
[php]
|
|
class m101129_185401_create_news_table extends CDbMigration
|
|
{
|
|
public function up()
|
|
{
|
|
$transaction=$this->getDbConnection()->beginTransaction();
|
|
try
|
|
{
|
|
$this->createTable('tbl_news', array(
|
|
'id' => 'pk',
|
|
'title' => 'string NOT NULL',
|
|
'content' => 'text',
|
|
));
|
|
$transaction->commit();
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
echo "Exception: ".$e->getMessage()."\n";
|
|
$transaction->rollback();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// ...similar code for down()
|
|
}
|
|
~~~
|
|
|
|
Porém, uma maneira mais fácil de obter o suporte a transações é implementar o método `safeUp()` ao invés de `up()`, e `safeDown()` ao invés de `down()`. Por exemplo,
|
|
|
|
~~~
|
|
[php]
|
|
class m101129_185401_create_news_table extends CDbMigration
|
|
{
|
|
public function safeUp()
|
|
{
|
|
$this->createTable('tbl_news', array(
|
|
'id' => 'pk',
|
|
'title' => 'string NOT NULL',
|
|
'content' => 'text',
|
|
));
|
|
}
|
|
|
|
public function safeDown()
|
|
{
|
|
$this->dropTable('tbl_news');
|
|
}
|
|
}
|
|
~~~
|
|
|
|
Quando o Yii realizar a migração, ele iniciará uma transação do banco de dados e então chamará `safeUp()` ou `safeDown()`. Se algum ocorrer algum erro do banco de dados em `safeUp()` ou `safeDown()`, a transação será revertida, o que garante que o banco de dados continue em boa forma.
|
|
|
|
> Note|Nota: Nem todos os SGBD suportam transações. E algumas cosultas do banco de dados
|
|
> não podem ser postas em uma transação. Neste caso, você terá que implementar `up()` e
|
|
> `down()`. E, para o MySQL, alguns comandos SQL podem causar
|
|
> [commits implícitos](http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html).
|
|
|
|
|
|
Aplicação Migrações
|
|
-------------------
|
|
|
|
Para aplicar todas as novas migrações disponíveis (o que significa deixar o banco de dados local atualizado),execute o seguinte comando:
|
|
|
|
~~~
|
|
yiic migrate
|
|
~~~
|
|
|
|
O comando irá mostras a lista de todas as novas migrações. Se você confirmar apply a aplicaçao das migrações, ele chamará o método `up()` em cada nova classe de migração, uma após a outra, na ordem do valor do "carimbo de tempo" em cada nome de classe.
|
|
|
|
Após aplicar a migração, a ferramenta de migração manterá um registro em uma tabela chamada `tbl_migration` no banco de dados. Isto permite que a ferramenta identifique quais migrações já foram aplicadas e quais não foram. Se a tabela `tbl_migration` não existir, a ferramenta a criará automaticamente no banco de dados especificado pelo componente de aplicação `db`.
|
|
|
|
Algumas vezes, nós podemos querer aplicar somente uma ou algumas das migrações. Nós podemos usar o comando abaixo:
|
|
|
|
~~~
|
|
yiic migrate up 3
|
|
~~~
|
|
|
|
Este comando aplicará as 3 novas migrações. Alterando o valor "3" nos permitirá alterar o número de migrações a serem aplicadas.
|
|
|
|
Nós podemos também migrar para uma versão específica do banco de dados com o seguinte comando:
|
|
|
|
~~~
|
|
yiic migrate to 101129_185401
|
|
~~~
|
|
|
|
Isto é, nós usamos a parte do "carimbo de tempo" do nome de uma migração para especificar a versão para a qual nós desejamos migrar o banco de dados. Se há múltiplas migrações entre a última migração aplicada e migração especificada, todas estas migrações serão aplicadas. Se a migração especificada já foi aplicada antes, então todas as migrações aplicadas depois dela serõ revertidas (a ser descrito na próxima seção).
|
|
|
|
|
|
Revertendo Migrações
|
|
--------------------
|
|
|
|
Para reverter a última ou algumas das últimas migrações aplicadas, nós podemos usar o seguinte comando:
|
|
|
|
~~~
|
|
yiic migrate down [step]
|
|
~~~
|
|
|
|
Onde o parâmetro opcional `step` especifica quantas migrações devem ser revertidas. O padrão é 1, o que significa que a última migração aplicada será revertida.
|
|
|
|
Como nós descrevemos antes, nem todas as migrações podem ser revertidas. Se você tentar reverter uma destas migrações, será lançada uma exceção e todo o processo de reversão será encerrado.
|
|
|
|
|
|
Reaplicando Migrações
|
|
---------------------
|
|
|
|
Reaplicar uma migração significa primeiro reverter e então aplicar a migração especificada. Isto pode ser feito com o comando a seguir:
|
|
|
|
~~~
|
|
yiic migrate redo [step]
|
|
~~~
|
|
|
|
onde o parâmetro opcional`step` especifica quantas migrações serão reaplicadas. O padrão é 1, o que significa que a última migração aplicada será reaplicada.
|
|
|
|
|
|
Exibindo Informações da Migração
|
|
--------------------------------
|
|
|
|
Além de aplicar e reverter migrações, a ferramenta de migrações também pode exibir o histórico de migrações e as novas migrações a serem aplicadas.
|
|
|
|
~~~
|
|
yiic migrate history [limit]
|
|
yiic migrate new [limit]
|
|
~~~
|
|
|
|
Onde o parâmetro opcional `limit` especifica o número de aplicações a serem exibidas. Se `limit` não é especificado, todas as migrações disponíveis serão exibidas.
|
|
|
|
O primeiro comando exibe as migrações que foram aplicadas, enquanto o segundo mostra as migrações que não foram aplicadas.
|
|
|
|
|
|
Modificando o Histórico de Migrações
|
|
------------------------------------
|
|
|
|
Algumas vezes, nós podemos querer modificar o histórico de migrações para uma versão de migração específica sem de fato aplicar ou reverter as migrações relevantes. Isto acontece frequentemente quando estamos criando uma nova migração. Nós podemos usar o comando a seguir para atingir este objetivo.
|
|
|
|
~~~
|
|
yiic migrate mark 101129_185401
|
|
~~~
|
|
|
|
Este comando é muito similar ao comando `yiic migrate to`, exceto que ele apenas modifica a tabela do histórico de migrações para a migração especificada sem aplicar ou reverter migrações.
|
|
|
|
|
|
Personalizando o Comando de Migração
|
|
------------------------------------
|
|
|
|
Há algumas maneiras de personalizar o comando de migração.
|
|
|
|
### Use Opções de Linha de Comando
|
|
|
|
O comando de migração possui quatro opções que podem ser especificadas na linha de comando:
|
|
|
|
* `interactive`: boolean, especifica se as migrações devem ser executadas em modo interativo. O padrão é `true`, o que significa que o usuário será perguntado quando executar uma migração específica. Você pode alterar esta opção para `false` quando as migrações são feitas por um processo em background.
|
|
|
|
* `migrationPath`: string, espeficica o diretório contendo todos os arquivos das classes de migrações. Esta opção deve ser especificada como um path alias (apelido para caminho), e o diretório correspondente deve existir. Se não for especificado, será usado o subdiretório `migrations` sob o caminho base da aplicação.
|
|
|
|
* `migrationTable`: string, especifica o nome da tabela do banco de dados para armazenar o histórico de migrações. O padrão é `tbl_migration`. A estrutura da tabela é `version varchar(255) primary key, apply_time integer`.
|
|
|
|
* `connectionID`: string, especifica o ID do componente de banco de dados da aplicação. O padrão é 'db'.
|
|
|
|
* `templateFile`: string, especifica o caminho do arquivo que servirá de modelo para a geração das classes de migração. Esta opção deve ser especificada como um path alias (por exemplo `application.migrations.template`). Se não for configurado, um modelo interno será usado. Dentro do modelo, o símbolo `{ClassName}` será substituído pelo nome real da classe da migração.
|
|
|
|
Para especificar estas opções, execute o comando de migração com o seguinte formato
|
|
|
|
~~~
|
|
yiic migrate up --option1=value1 --option2=value2 ...
|
|
~~~
|
|
|
|
Por exemplo, se nós queremos migrar para um módulo `forum` cujos arquivos de migração estejam localizados no diretório `migrations` do módulo, nós podemos usar o comando abaixo:
|
|
|
|
~~~
|
|
yiic migrate up --migrationPath=ext.forum.migrations
|
|
~~~
|
|
|
|
|
|
### Configurar o Comando Globalmente
|
|
|
|
Enquanto as opções de linha de comando nos permitem configurar o comando de migração dinamicamente, algumas vezes nós podemos querer configura o comando uma vez para todas as execuções. Por exemplo, nós podemos querer usar uma tabela diferente para armazenar o histórico de migrações, ou nós podemos querer usar um modelo de migração personalizado. Nós podemos fazer isto modificando o arquivo de configuração da aplicação de console como a seguir,
|
|
|
|
~~~
|
|
[php]
|
|
return array(
|
|
......
|
|
'commandMap'=>array(
|
|
'migrate'=>array(
|
|
'class'=>'system.cli.commands.MigrateCommand',
|
|
'migrationPath'=>'application.migrations',
|
|
'migrationTable'=>'tbl_migration',
|
|
'connectionID'=>'db',
|
|
'templateFile'=>'application.migrations.template',
|
|
),
|
|
......
|
|
),
|
|
......
|
|
);
|
|
~~~
|
|
|
|
Agora, se nós executarmos o comando `migrate`, a configuração acima fará efeito sem ser necessário usar as opções de linha de comando em todas as vezes.
|
|
|
|
|
|
<div class="revision">$Id$</div>
|