Quando nossa equipe inicia um determinado projeto, costumamos reunir para discutir sobre a estrutura do banco de dados, como as regras de negócio serão implementadas e os dados serão gravados para tudo funcionar o mais perfeito possível. Desta discussão, já montamos o primeiro modelo de relacionamentos das tabelas no banco de dados. Costuma ser um modelo rápido feito no WorkBench.
Acredito que este processo seja parecido em diversas empresas de desenvolvimento, quando estão iniciando um projeto. Agora apresento algumas facilidades e seguranças que os Migrations do Laravel implementam para a montagem da estrutura do seu banco de dados, assim como seu relacionamento como um todo.
Como exemplo prático, montei este banco que simula o catálogo de produtos de uma loja. Este banco possui os produtos e seu relacionamento com a linha de produtos.
Criando as Migrations
O conceito de migrations trazido pelo Laravel permite o controle de versões e assim facilitar a modificação e compartilhamento da estrutura do banco de dados entre equipes. Imagine você mexendo em um projeto, em seu ambiente de desenvolvimento. Você cria uma nova coluna em seu banco de dados e continua desenvolvendo seu código normalmente. Sem as migrations seu colega pega seu código coloca no ambiente de desenvolvimento dele e tenta rodar. É claro que teremos diversos erros disparando na tela deste cara.
Agora com as migrations seu colega de trabalho verá nos registros de versionamento do código que teve uma atualização de arquivos na pasta “migrations” e então basta ele rodar o comando php artisan migrate que seu banco estará totalmente atualizado.
Para criar uma migration, durante o desenvolvimento do código é importante que tenhamos uma configuração de banco de dados. Afinal no fim das contas as migrations irão produzir um banco de dados.
Para configurá-lo basta setar as configurações do banco de dados, criado em seu servidor, dentro do arquivo .env que fica na raiz do projeto.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_store
DB_USERNAME=fmv
DB_PASSWORD=$%SDFFHHJ
Ahhh, quase ia me esquecendo! Se você chegou aqui mas está perdido em como instalar o Laravel, tenho o primeiro artigo desta série.
Tudo configurado, agora vamos gerar nossas novas classes de migrations. Isto tudo será feito através do comando artisan make:migration.
php artisan make:migration create_product_line --create=product_line
php artisan make:migration create_product --create=product
Ao final de cada comando, vocês podem ver que adicionei a opção –create. Esta opção permite que eu defina o nome da tabela que eu estou criando. Existem outras opções para este comando que vocês podem ver na documentação completa do Laravel 5.5.
A estrutura da migration é simples. Ela importa as classes Schema, Blueprint e Migration e possui 2 funções:
UP
Esta função é a responsável pela implementação das atualizações do banco. criar uma tabela, atualizar uma coluna e etc.
Down
É a função que fará exatamente o inverso da função UP revertendo seu banco de dados ao estado anterior a esta atualização.
Então, minhas classes ficaram desta forma.
create_product
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class create_product extends Migration
{
public function up() {
Schema::create('product', function (Blueprint $table) {
$table->smallIncrements('id');
$table->string('description')->unique();
$table->string('expiration_date');
$table->decimal('price', 5, 2);
$table->timestamps();
$table->engine = 'InnoDB';
});
}
public function down() {
Schema::drop('product');
}
}
create_product_line
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class create_product_line extends Migration
{
public function up() {
Schema::create('product_line', function (Blueprint $table) {
$table->smallIncrements('id');
$table->string('description')->unique();
$table->timestamps();
$table->engine = 'InnoDB';
});
}
public function down() {
Schema::drop('product');
}
}
Acima você vai ver que existe uma definição que não estava em meu diagrama. $table->timestamps(); Isto é um padrão do Eloquent do Laravel para controlar quando um dado é criado e atualizado.
Outra definição do diagrama porém, não foi incluída de propósito. Fiz isto para chegar finalmente ao objetivo deste post. Os relacionamentos entre as tabelas.
Relacionando tabelas
Com as migrations é possível criar foreign keys e definir o relacionamento entre as tabelas do seu banco de dados. Este relacionamento cria restrições que protegem a integridade dos dados suas tabelas.
Para criar este relacionamento é bem simples. Voltemos ao nosso exemplo no arquivo create_product
…
Schema::create('products', function (Blueprint $table) {
$table->smallIncrements('id');
$table->smallInteger('product_line_id');
$table->string('description','100')->unique();
$table->integer('expiration_time');
$table->decimal('price',5,2);
$table->timestamps();
$table->foreign('product_line_id')
->references('id')
->on('product_lines');
});
…
Traduzindo a linha nova, temos uma Foreign key que referencia à coluna “id” na tabela “product_line”.
Além disto é possível adicionar restrições para qualquer ação de atualização (onUpdate) e exclusão (onDelete) de registros dentro da tabela. Neste caso tratarei para que sempre que houver a exclusão de uma linha de produtos este perca a referência com a tabela product_line (Setar como nulo).
…
$table->integer('unit_id')
->unsigned()
->nullable();
…
$table->foreign('product_line_id')
->references('id')
->on('product_line')
->onDelete('set null');
$table->timestamps();
});
…
Desta forma eu permito que uma linha de produto seja excluído. Claro que aqui o produto ficará orfão de uma linha de produto. Mas, por enquanto estamos apenas trabalhando as regras do banco.
Removendo um relacionamento
Apenas para concluir… Se quiser remover o relacionamento criado isto é possível utilizando o método dropForeign.
$table->dropForeign(['product_line_id']);
Agora que as migrations estão completas o próximo passo será definir as Models. Mas, este fica pro próximo artigo. 🙂