Skip to main content
Chapter 3 Eloquent ORM and Database Mastery

Migrations and Schema Builder

20 min read Lesson 9 / 28

Database Migrations: Version Control for Your Schema

Migrations let you define your database schema in PHP code, making it versionable, shareable, and deployable.

Creating a Migration

php artisan make:migration create_posts_table
return new class extends Migration
{
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->foreignId('category_id')->constrained();
            $table->string('title');
            $table->string('slug')->unique();
            $table->text('excerpt')->nullable();
            $table->longText('body');
            $table->string('cover_image')->nullable();
            $table->boolean('is_published')->default(false)->index();
            $table->boolean('is_featured')->default(false);
            $table->timestamp('published_at')->nullable();
            $table->unsignedInteger('views_count')->default(0);
            $table->timestamps();

            // Composite index for common queries
            $table->index(['is_published', 'published_at']);
        });
    }

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

Column Modifiers

$table->string('email')->unique();
$table->text('bio')->nullable();
$table->integer('sort_order')->default(0);
$table->decimal('price', 10, 2)->unsigned();
$table->enum('status', ['draft', 'published', 'archived']);
$table->json('metadata')->nullable();
$table->softDeletes(); // Adds deleted_at column

Modifying Existing Tables

php artisan make:migration add_subtitle_to_posts_table
public function up(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->string('subtitle')->nullable()->after('title');
    });
}

public function down(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->dropColumn('subtitle');
    });
}

Migration Commands

php artisan migrate              # Run pending migrations
php artisan migrate:rollback     # Undo last batch
php artisan migrate:status       # Check migration status
php artisan migrate:fresh --seed # Drop all, re-migrate, seed

Always write a down() method so migrations are reversible. In production, use php artisan migrate --force in your deployment script.