Como criar uma Migration
Tutorial: Criando uma Migration no Laravel
Este tutorial demonstra o processo completo de criação de uma migration no Laravel utilizando como exemplo a tabela .usuariosusuario
Ao final deste guia você será capaz de:
- Criar uma migration;
- Definir a conexão do banco utilizada;
- Criar tabelas e colunas;
- Definir chaves primárias;
- Definir restrições de unicidade;
- Utilizar enums;
- Executar migrations;
- Reverter migrations;
- Compreender os tipos de colunas mais utilizados.
1. O que é uma Migration?
Uma migration é um arquivo PHP responsável por definir a estrutura do banco de dados.
Ela funciona como um controle de versão do banco.
Em vez de executar manualmente comandos SQL como:
CREATE TABLE usuarios (...);
o Laravel utiliza migrations:
Schema::create('usuarios', function (Blueprint $table) {
...
});
Isso permite que toda a equipe mantenha o banco sincronizado.
2. Criando uma Migration
Para criar uma migration:
php artisan make:migration create_usuarios_table
Será criado um arquivo semelhante a:
database/migrations/
└── 2026_06_10_144334_create_usuarios_table.php
Caso o projeto utilize uma pasta específica:
php artisan make:migration create_usuarios_table \
--path=database/migrations/selecao_prppg
3. Estrutura básica de uma Migration
Toda migration possui dois métodos:
public function up(): void
{
// cria ou altera tabelas
}
public function down(): void
{
// desfaz alterações
}
Método up()
Primeiro entramos no ouath-server:
docker exec -it oauth-server bash
Executado quando rodamos:
php artisan migrate --path=database/migrations/selecao_prppg/ --database=pgsql_selecao_prppg
Método down()
Executado quando queremos rever a última migration:
php artisan migrate:rollback --path=database/migrations/selecao_prppg/ --database=pgsql_selecao_prppg
php artisan migrate:fresh --path=database/migrations/selecao_prppg/ --database=pgsql_selecao_prppg
4. Definindo a conexão do banco
No projeto de vocês existe mais de uma conexão.
Por isso foi definido:
protected $connection = 'pgsql_selecao_prppg';
Isso indica que a migration será executada utilizando a conexão:
DB_CONNECTION=pgsql_selecao_prppg
configurada em:
config/database.php
5. Tratamento para ambiente de testes
No construtor:
public function __construct()
{
if (app()->environment('testing')) {
$this->connection = 'pgsql_testing';
}
}
Quando os testes automatizados forem executados:
php artisan test
a migration utilizará:
pgsql_testing
em vez de:
pgsql_selecao_prppg
evitando alterações no banco real.
6. Verificando se a tabela já existe
Antes da criação:
if (!Schema::hasTable('usuarios'))
O Laravel verifica:
SELECT ...
FROM information_schema.tables
Se a tabela já existir:
usuarios
ela não será criada novamente.
7. Criando a tabela
A criação da tabela ocorre através de:
Schema::create('usuarios', function (Blueprint $table) {
...
});
Equivalente ao SQL:
CREATE TABLE usuarios (...);
8. Criando a chave primária
Código:
$table->id()
->autoIncrement()
->primary()
->comment('Id do Usuario');
Resultado:
id BIGINT PRIMARY KEY AUTO_INCREMENT
Observação:
No Laravel moderno geralmente basta:
$table->id();
pois o framework já cria:
- auto increment
- primary key
automaticamente.
9. Criando campos texto
Nome:
$table->string('nome', 100);
Resultado:
VARCHAR(100)
Email:
$table->string('email', 100);
Resultado:
VARCHAR(100)
CPF:
$table->string('cpf', 11);
Resultado:
VARCHAR(11)
10. Definindo valores únicos
Email:
$table->string('email', 100)->unique();
Resultado:
UNIQUE(email)
Não será possível cadastrar dois usuários com o mesmo email.
CPF:
$table->string('cpf', 11)->unique();
Resultado:
UNIQUE(cpf)
11. Trabalhando com datas
Campo:
$table->dateTime('data_cadastro');
Resultado:
DATETIME
ou
TIMESTAMP
dependendo do banco.
Exemplo:
2026-06-10 14:30:00
12. Trabalhando com Enum
Campo:
$table->enum('cargo', [
'SECRETARIA',
'COORDENADOR',
'COMISSAO',
'ADMINISTRADOR'
]);
Resultado:
ENUM(...)
Valores permitidos:
SECRETARIA
COORDENADOR
COMISSAO
ADMINISTRADOR
Qualquer outro valor será rejeitado.
13. Campo senha
Campo:
$table->string('senha', 60);
Resultado:
VARCHAR(60)
Normalmente armazenará um hash:
$2y$12$...
e não a senha em texto puro.
14. Timestamps automáticos
Código:
$table->timestamps();
Cria automaticamente:
created_at
updated_at
Exemplo:
| Campo | Função |
|---|---|
| created_at | Data de criação |
| updated_at | Última alteração |
15. Executando a Migration
Após criar o arquivo:
php artisan migrate
O Laravel:
- Localiza migrations pendentes.
- Executa o método
up(). - Registra a execução na tabela:
migrations
16. Verificando o status
php artisan migrate:status
Exemplo:
Migration name Ran?
-----------------------------------------
create_usuarios_table Yes
17. Revertendo a Migration
Desfaz a última migration executada:
php artisan migrate:rollback
Executa:
public function down()
{
Schema::dropIfExists('usuarios');
}
18. Recriando tudo
Muito utilizado durante desenvolvimento:
php artisan migrate:fresh
Apaga todas as tabelas e executa novamente todas as migrations.
Comandos mais utilizados
| Comando | Função |
|---|---|
php artisan make:migration nome |
Criar migration |
php artisan migrate |
Executar migrations |
php artisan migrate:status |
Ver status |
php artisan migrate:rollback |
Desfazer última migration |
php artisan migrate:fresh |
Recriar banco |
php artisan migrate --path=... |
Executar pasta específica |
Tipos de colunas mais utilizados
| Sintaxe | Tipo SQL |
|---|---|
$table->id() |
BIGINT PK |
$table->string('nome') |
VARCHAR(255) |
$table->string('nome',100) |
VARCHAR(100) |
$table->text('descricao') |
TEXT |
$table->integer('idade') |
INT |
$table->bigInteger('codigo') |
BIGINT |
$table->decimal('valor',10,2) |
DECIMAL |
$table->boolean('ativo') |
BOOLEAN |
$table->date('inicio') |
DATE |
$table->dateTime('inicio') |
DATETIME |
$table->timestamp('inicio') |
TIMESTAMP |
$table->enum('status',[...]) |
ENUM |
$table->json('dados') |
JSON |
Modificadores mais utilizados
| Sintaxe | Função |
|---|---|
->nullable() |
Permite NULL |
->default('X') |
Valor padrão |
->unique() |
Valor único |
->comment('texto') |
Comentário da coluna |
->index() |
Cria índice |
->primary() |
Define PK |
->autoIncrement() |
Auto incremento |
Relacionamentos (Foreign Keys)
Os mais utilizados no projeto Guavira serão:
Forma moderna
$table->foreignId('programa_id')
->constrained('programas');
Com cascade
$table->foreignId('programa_id')
->constrained('programas')
->cascadeOnDelete();
Forma explícita
$table->unsignedBigInteger('programa_id');
$table->foreign('programa_id')
->references('id')
->on('programas');
Métodos mais utilizados no projeto
Ao criar as tabelas programas, editais, linhas_pesquisa, inscricoes, resultados e demais entidades do sistema, você utilizará principalmente:
| Método | Frequência |
|---|---|
$table->id() |
Muito alta |
$table->string() |
Muito alta |
$table->foreignId() |
Muito alta |
->constrained() |
Muito alta |
$table->date() |
Alta |
$table->enum() |
Alta |
$table->timestamps() |
Muito alta |
->nullable() |
Alta |
->unique() |
Média |
->cascadeOnDelete() |
Média |
Esses métodos são suficientes para construir praticamente todas as tabelas do banco do sistema de seleção PRPPG/Guavira.
Caso Especial: Migration realizada em banco de dados incorreto
Por padrão, as migrations do sistema são registradas no banco da api (oauth-postgres), visto que ele precisa centralizar todas as tabelas da aplicação. Por esse motivo, pode ocorrer situações em que as migrations não ocorrem da maneira esperada visto que elas "já estão criadas".
Caso você queira reverter as migrations do seu banco, deve fazer o seguinte:
Acessar o container do seu banco, como por exemplo o selecao_prppg, entrar no psql e apagar o banco de dados atual, em sequência, você deve criar novamente o banco de dados, que desta vez estará em branco e livre para suportar novas migrations.
Em sequência, você deve acessar o banco de dados da api e verificar as migrations a partir do seguinte comando:
SELECT * FROM migrations
Como resultado, você terá acesso a todas as migrations registradas naquele banco, seu nome e seus id's. A partir dessa informação, devemos realizar o delete das migrations que iremos refazer, utilizando o comando:
DELETE FROM migrations WHERE id = (condição)
Em sequência, podemos realizar as migrations do sistema, que dessa vez não terão nenhum empecilho as impedindo e poderão ser recriadas do zero.