Boas Práticas de Laravel Migrations e Seeders na Prática para Times Ágeis Já leu

Entendendo Migrations: Versionamento do Seu Banco de Dados Migrations no Laravel funcionam como um sistema de controle de versão para sua estrutura de banco de dados. Em vez de criar tabelas manualmente via SQL, você define-as através de código PHP que pode ser rastreado, compartilhado e revertido. Isso é fundamental em projetos colaborativos onde múltiplos desenvolvedores precisam manter o esquema do banco sincronizado. Uma migration é basicamente uma classe que descreve alterações no banco de dados. Ela contém dois métodos: (o que fazer) e (como desfazer). Laravel cria um arquivo com timestamp automático para garantir que as migrações rodem sempre na ordem correta. Aqui você vê a estrutura típica: o método cria a tabela com suas colunas, e a remove. O timestamp no nome do arquivo garante que esta migration rode antes de uma criada depois. Use para executar todas as migrações pendentes e para desfazer a última batida de migrações. Criando Migrations com Gerador O Laravel oferece um comando

Entendendo Migrations: Versionamento do Seu Banco de Dados

Migrations no Laravel funcionam como um sistema de controle de versão para sua estrutura de banco de dados. Em vez de criar tabelas manualmente via SQL, você define-as através de código PHP que pode ser rastreado, compartilhado e revertido. Isso é fundamental em projetos colaborativos onde múltiplos desenvolvedores precisam manter o esquema do banco sincronizado.

Uma migration é basicamente uma classe que descreve alterações no banco de dados. Ela contém dois métodos: up() (o que fazer) e down() (como desfazer). Laravel cria um arquivo com timestamp automático para garantir que as migrações rodem sempre na ordem correta.

// database/migrations/2024_01_15_100000_create_users_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Aqui você vê a estrutura típica: o método up() cria a tabela com suas colunas, e down() a remove. O timestamp no nome do arquivo garante que esta migration rode antes de uma criada depois. Use php artisan migrate para executar todas as migrações pendentes e php artisan migrate:rollback para desfazer a última batida de migrações.

Criando Migrations com Gerador

O Laravel oferece um comando que cria migrations com boilerplate pronto. Para criar uma nova tabela, use:

php artisan make:migration create_posts_table --create=posts

Se você quer alterar uma tabela existente:

php artisan make:migration add_status_to_users_table --table=users

No segundo caso, o método up() vem com a estrutura para modificação:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('status')->default('active');
        $table->softDeletes();
    });
}

Repare que usamos Schema::table() para alterar tabelas existentes, enquanto Schema::create() é para criar novas. Detalhes como este fazem diferença real em produção.

Seeders: Populando Dados de Forma Inteligente

Se migrations definem a estrutura, seeders definem os dados iniciais. Um seeder é uma classe que insere registros no banco durante desenvolvimento ou setup inicial. Isso evita que você insira dados manualmente ou através de SQL puro.

Crie um seeder com php artisan make:seeder PostSeeder. Laravel gera um arquivo em database/seeders/PostSeeder.php:

namespace Database\Seeders;

use App\Models\Post;
use Illuminate\Database\Seeder;

class PostSeeder extends Seeder
{
    public function run()
    {
        Post::create([
            'title' => 'Primeiro Post',
            'content' => 'Conteúdo do post...',
            'author_id' => 1,
        ]);

        Post::create([
            'title' => 'Segundo Post',
            'content' => 'Mais conteúdo...',
            'author_id' => 1,
        ]);
    }
}

Factories: Gerando Dados em Massa

Para dados de teste ou desenvolvimento, factories são muito mais práticas que inserir registros um por um. Uma factory define como gerar dados fictícios realistas usando a biblioteca Faker:

// database/factories/PostFactory.php
namespace Database\Factories;

use App\Models\Post;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    protected $model = Post::class;

    public function definition()
    {
        return [
            'title' => $this->faker->sentence(5),
            'content' => $this->faker->paragraph(4),
            'author_id' => \App\Models\User::factory(),
            'published_at' => $this->faker->optional()->dateTime(),
        ];
    }
}

Agora seu seeder pode usar a factory para gerar múltiplos registros:

public function run()
{
    // Cria 50 posts com dados realistas
    Post::factory(50)->create();

    // Ou criar com relações
    Post::factory(10)->for(User::first())->create();
}

Isso economiza linhas de código e torna dados de teste mais realistas.

Executando Seeders de Forma Organizada

O DatabaseSeeder funciona como maestro que orquestra todos os seus seeders:

// database/seeders/DatabaseSeeder.php
namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call([
            UserSeeder::class,
            PostSeeder::class,
            CommentSeeder::class,
        ]);
    }
}

Execute tudo com um único comando:

php artisan db:seed

Para rodar um seeder específico:

php artisan db:seed --class=PostSeeder

Uma abordagem profissional combina migrations com seeders no setup completo:

php artisan migrate:fresh --seed

Este comando apaga tudo e reconstrói o banco do zero, rodando migrations e seeders. Perfeito para desenvolvimento local ou ambientes de teste.

Boas Práticas e Casos Reais

Em projetos reais, você terá migrações complexas com relacionamentos, índices e constraints. Sempre crie relacionamentos corretamente:

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('content');
    $table->foreignId('user_id')->constrained('users')->onDelete('cascade');
    $table->timestamps();

    $table->index('user_id');
    $table->fullText('title', 'content'); // para busca
});

Use foreignId() e constrained() para criar foreign keys com integridade referencial. O onDelete('cascade') garante que posts sejam deletados se o usuário for deletado.

Para dados sensíveis ou padrões em produção, considere separar seeders de desenvolvimento:

php artisan make:seeder --seed=local AdminUserSeeder

Coloque dados reais apenas em seeders específicos, nunca hardcode credenciais. Use variáveis de ambiente quando necessário dados sensíveis.

Conclusão

Migrations e seeders são pilares de um workflow profissional em Laravel. Primeiro ponto: migrations dão versionamento e reversibilidade ao seu schema — sempre use migrations, nunca SQL direto em produção. Segundo ponto: combine seeders com factories para popular dados de forma escalável e mantível. Terceiro ponto: organize seu DatabaseSeeder para orquestrar múltiplos seeders em ordem lógica, e sempre teste migrate:fresh --seed antes de fazer deploy.

Domine estes conceitos agora e você terá uma base sólida para trabalhar com Laravel em qualquer escala.

Referências


Artigos relacionados