Versionamento de Banco de Dados no Laravel
Aprenda a usar as Migrations para criar tabelas e versioná-las garantindo uma base segura e estável.
Uma base estável
Todo desenvolvedor, seja ele back-end, front-end ou até mobile sabe que o coração de uma aplicação bem desenvolvida é o banco de dados, ele tem que ser bem configurado para que possa oferecer segurança e um longo ciclo de vida, na verdade, o ideal é o programador desenvolver o DB no início da aplicação e não precisar mais se preocupar com o mesmo, sem ter que renomear tabelas, concertando nomeclatura de relacionamentos e etc.
O Laravel por padrão fornece suporte para criação e manutenção de Banco de Dados, isso significa que ele pode criar tabelas e seus campos, versionar o banco de dados de tal forma em que o programador possa ‘voltar’ até a versão anterior, o framework pode até inserir múltiplos dados ‘fake’ de uma vez para que o programador na fase de desenvolvimento possa trabalhar com esses registros simulando a aplicação em funcionamento.
Porém, para esse texto não ficar muito longo, irei apenas explicar e demonstrar o uso de Migrations e suas possibilidades dentro do Framework.
Migrations
Migrations (ou migrações) são recursos que não se limitam somente ao ecossistema do Laravel, eles estão disponíveis em outros frameworks, e isso enfatiza a necessidade de entender o conceito da mesma, tendo em consideração que você poderá usar em vários tipos de projetos.
Versionamento e Criação de Tabelas
As Migrations são conhecidas por versionar o banco de dados, mas o que isso significa?
Vamos supor que você cria uma tabela no banco de dados, configura ela bonitinha e está pronta para uso, mais pra frente, em um upgrade na aplicação, você precisa alterar alguns campos, colunas, e por falta de atenção acaba fazendo besteira e desconfigurando a tabela, e o pior, você não fez backup.
Se você tiver usado uma migration para criar a sua tabela no início, será só usar a mesma migration para restaurar sua base de dados ao estado original, ou melhor, a cada mudança importante na tabela, bastaria criar uma migration para o processo, e você poderia voltar para um estado específico do banco de dados onde ainda está tudo ok.
Esse é o significado de versionamento de database, você tem várias versões do seu banco e pode criar novas ou alternar entre elas de acordo com sua necessidade.
Criação da Migration
Vamos simular a criação de um banco de dados em MySQL para o cadastro de alguns livros, iremos criar duas tabelas: Livro e Autor com a relação de um (autor) para n (livros).
Será necessário criar apenas o Schema no banco de dados: ‘library’ (não irei entrar em detalhes de criação de banco de dados no MySQL pois não é o intuito do artigo).
Após a criação, vamos primeiramente configurar a conexão com o banco de dados, as principais configurações de um projeto Laravel ficam no dotfile ‘.env’ na raíz, dentro dele altere os valores:
DB_DATABASE=library # Nome do Schema criado
DB_USERNAME=root # Padrão MySQL/MariaDB
DB_PASSWORD= # Padrão (se não der certo tente 'root')Depois de setadas as variáveis de conexão, vamos criar as migrations para as tabelas ‘authors’ e ‘books’. Para criar a migration de authors, rode em um console aberto na raíz do projeto, o seguinte:
php artisan make:migration create_authors_table --create=authorsComando grande né? Fica mais fácil quando o entendemos:
php artisan: Executando o helper artisan com o interpretador PHP do sistemamake:migration: Criando uma migrationcreate_authors_table: Nome da migration, create_<nomeTabela>_table--create=authors: Flag para migration, significa que queremos uma migration de criação de tabela e essa tabela se chama ‘authors’
Métodos de ação
O arquivo da migration será encontrado em database/migrations e terá como nome um prefixo relativo à data atual + o nome especificado na criação (dentro da pasta terão outras migrations que vêm por padrão, não se preocupe com elas). No arquivo criado pelo comando acima, terá uma classe de criação de tabela que extende a classe Migration do framework, e dentro da classe terão dois métodos, o up e o down.
O método up tem a função de realizar a operação, ou seja, nesse caso o método up deve criar a tabela authors com os campos determinados. O método down tem como o objetivo desfazer o que o método up faz, ou seja, ele deverá dropar a tabela authors após criada.
No método up terá a execução do método estático ‘create’ da classe Schema, o que você precisa saber dele é que o primeiro parâmetro é a tabela que será criada, o segundo parâmetro é uma função anônima (callback) com os campos que essa tabela terá.
Verbos de criação
No método up (e down também), você vai se deparar com uma variável chamada table, de forma semântica, ela representa a tabela a ser criada. Ela tem alguns métodos que representam os tipo de campos a serem criados, no caso o método ‘id()’, é equivalente a um campo id int (número), não nulo, com auto increment e que será a chave primária.
Você pode acessar esse link para ver qual os métodos e suas funções dentro de uma tabela, mas os que iremos usar são esses:
Método Função Query
id() => Chave Primária => id INT NOT NULL PRIMARY KEY AUTO_INCREMENT Método Função Query
string(nome_campo) => Campo de String => nome_campo VARCHAR(255)Método Função Query
integer(numero) => Número Iteiro => numero INTEGERMétodo Função
foreignId(foreign_key) => Chave Estrangeira
Pronto! Agora que já entendemos os métodos e temos nossa migration criada, vamos configurar ela, a tabela de autores terá os campos ‘id’, ‘name’ e ‘email’. Então bora lá, adicione os seguintes métodos ao método up:
Schema::create('authors', function (Blueprint $table) {
$table->id();
$table->string('name'); // O email deve ser unico
$table->string('email')->unique(); // Não serão necessárias as tabelas de timestamps });
Então está ok, Migration de autores configurada, vamos criar a migration de livros, já sabemos o processo, no console digite:
php artisan make:migration create_authors_table --create=authorsAgora no arquivo criado, configure os campos ‘title’, ‘pages’ e ‘author’, sendo o author uma Foreign Key ele terá algumas particularidades:
Schema::create('books', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->integer('pages');
$table->foreignId('author'); // A chave estrangeira 'author'
$table->foreign('author') // referencia o campo 'id'
->references('id') // Na tabela 'authors'
->on('authors') // Deleção em cascata, caso ocorra
->onDelete('CASCADE'); // Não serão necessárias as tabelas de timestamps
});
Agora que estão as duas migrations estão criadas, vamos rodar as mesmas para que as tabelas sejam criadas no banco de dados, para isso usamos o ‘migrate’ do artisan:
php artisan migrateNessa parte, talvez possam ocorrer erros, caso aconteçam, tente dar uma lida no erro retornado, cheque seu .env se está tudo certinho ou então veja a sintaxe das migrations pra confirmar.
Rollbacks
Putz! Esquecemos de adicionar o campo de editora do livro e a tabela já está criada, vamos ter que entrar no Workbench ou no console MySQL e dar um alter table para consertar isso?
Não, claro que não, as migrations nos fornecem algumas maneiras de consertar esse erro, a primeira maneira é fazendo um rollback.
Rollback não é nada mais que a ação ‘voltar’ ou ‘desfazer’, aquele lance de migration que eu disse antes, quando queremos voltar uma versão usamos o rollback para isso, ele por baixo dos panos irá executar todos os métodos down das migrations, e como você sabe, o método down desfaz tudo o que o up faz, lógicamente, iremos desfazer o que foi feito, voltando a um estado anterior.
Para voltar todo o banco de dados, digite no console:
php aritsan migrate:rollbackAgora se você der uma olhada no seu DB verá que ele está vazio, vamos alterar aquela migration de livros e adicionar o campo ‘publisher’ que é a editora responsável pela publicação do livro:
Schema::create('books', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->integer('pages'); // Agora sim
$table->string('publisher'); $table->foreignId('author'); $table->foreign('author')
->references('id')
->on('authors')
->onDelete('CASCADE');});
Tudo alterado, tudo certo. Vamos rodar a migration e recriar a tabela (sem erros dessa vez).
php artisan migrateRefreshs
Não! Espera! Esquecemos do campo de verificação de email dos autores, vamos ter que dar outro rollback para arrumar isso?.
Talvez, o framework permite que eu faça o processo anterior quantas vezes eu queira, mas como eu disse anteriormente, o Laravel possui algumas maneiras de consertar esse erro, vamos abordar o uso de refreshs.
Dá pra dizer que o refresh é um rollback automatizado, ele irá rodar todos os métodos down e logo em seguida rodar todos os up, sem a necessidade de rodar um migrate depois.
Vamos adicionar esse campo na migration e ver como que o refresh funciona e se ele é tudo isso mesmo:
Schema::create('authors', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique(); // Vai receber a data de verificação de e-mail, pode ser nulo
$table->timestamp('email_verified_at')->nullable(); });
Agora vamos no console:
php artisan migrate:refreshApós o comando, todas as tabelas serão desfeitas e refeitas, mas dessa vez com os campos corretos.
Migration de Tabelas
Existe uma outra maneira de fazer esse tipo de ação, adicionar um campo a uma tabela já existente. Nas maneiras anteriores, caso você já tenha escrito dados no DB, eles serão perdidos no momento de execução dos métodos down. Essa maneira é tão simples como as outras e você não irá perder seus registros.
Vamos simplesmente criar uma outra migration, mas não de criação de tabela, uma de adição de campo:
php artisan make:migration add_email_verify_authors --table=authorsVeja que o comando é diferente, nesse usamos o ‘add_<name>_<tabela>’ e trocamos a flag ‘create’ por ‘table’, tudo isso é levado em consideração pelo artisan e é um padrão que deve ser seguido.
A migration vai ser encontrada no mesmo diretório das outras, ela terá a mesma estrutura de up e down, mas veja que nessa o método de Schema não é ‘create’ mas ‘table’, pois não estamos alterando nenhum schema, mas sim uma tabela.
Dentro dele vamos adicionar o nosso campo ‘email_verified_at’ do mesmo modo que fizemos anteriormente, dentro do método up faça:
Schema::table('authors', function (Blueprint $table) { $table->timestamp('email_verified_at')->nullable();});
Se você reparar, o método down também precisa ser configurado, de acordo com a lógica de fazer o inverso do up, ele deve dropar a coluna criada acima, então vamos lá, dentro do down, configure:
Schema::table('authors', function (Blueprint $table) { $table->dropColumn('email_verified_at'); });
Tudo setado, como não precisamos voltar a versão de nosso banco de dados, vamos apenas dar um migrate simples, e o framework vai se encarregar de criar esse campo dentro da tabela do banco de dados sem alterar nenhum registro:
php artisan migrateO bom desse método, além de preservar os registros é que com o arquivo de migration criado, você acaba criando um ponto de versionamento, se algo de errado ocorrer futuramente, você poderá voltar a esse ponto.
Conclusão
Migration é um dos pilares principais do Laravel, muitos iniciantes aprendem a usar logo no início dos estudos no Framework, espero que a leitura tenha sido tranquila e que vocês tenham entendido ou relembrado a importância e o funcionamento desse recurso, eu tentei explicar da forma mais clara o possível mas é sempre recomendável que o desenvolvedor leia a documentação, lá tem MUITO mais do que foi falado aqui.
Leia a Documentação do Laravel a respeito de Migrations e a Documentação Oficial do Laravel 7.
