beginner Step 5 of 15

Migrations and Seeders

Laravel Framework

Migrations and Seeders

Migrations are version-controlled database schema definitions that let your team share and synchronize database structure changes. Instead of manually running SQL statements, you define schema changes in PHP classes that can be run forward (migrate) or backward (rollback). Seeders populate your database with test or default data. Together, migrations and seeders ensure every developer and deployment environment has an identical database setup.

Migrations

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->onDelete('cascade');
            $table->string('title');
            $table->string('slug')->unique();
            $table->text('body');
            $table->string('category')->default('general');
            $table->boolean('is_featured')->default(false);
            $table->timestamp('published_at')->nullable();
            $table->timestamps();   // created_at and updated_at
            $table->softDeletes();  // deleted_at

            $table->index(['category', 'published_at']);
        });
    }

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

// Run migrations
// php artisan migrate
// php artisan migrate:rollback
// php artisan migrate:fresh --seed  (drop all + re-run + seed)

Seeders and Factories

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

use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    public function definition(): array
    {
        return [
            'title' => fake()->sentence(),
            'slug' => fake()->unique()->slug(),
            'body' => fake()->paragraphs(5, true),
            'category' => fake()->randomElement(['tech', 'news', 'tutorial']),
            'published_at' => fake()->optional(0.8)->dateTimeBetween('-1 year'),
        ];
    }
}

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

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

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $admin = User::factory()->create([
            'name' => 'Admin User',
            'email' => 'admin@example.com',
        ]);

        Post::factory(50)->for($admin)->create();

        User::factory(10)->has(Post::factory(5))->create();
    }
}

// php artisan db:seed
Pro tip: Use php artisan migrate:fresh --seed during development to reset your database to a clean state with test data. In production, never use migrate:fresh — only run migrate to apply new migrations. Use factories with Faker to generate realistic test data automatically.

Key Takeaways

  • Migrations define database schema changes in PHP, enabling version-controlled database structure.
  • Use php artisan make:migration to create migrations and php artisan migrate to run them.
  • Factories generate fake data for testing using the Faker library.
  • Seeders populate the database with initial or test data using factories.
  • Never use migrate:fresh in production — it drops all tables.