0

What migrations are and why they exist

Beginner5 min read·lv-14-001
sqlinterview

Concept

Migrations are version-controlled database schema changes. Instead of manually altering the database or sharing SQL dump files, migrations are PHP files that describe schema changes in code — committed to the repository alongside application code.

Why migrations:

  • Version control: Schema changes are tracked in git, with history, authorship, and diffs.
  • Repeatability: Any developer can run php artisan migrate and get the same schema.
  • Environments: Dev, staging, and production schemas stay in sync.
  • Rollback: migrate:rollback undoes the last batch of migrations, enabling recovery from bad deploys.
  • Team collaboration: Multiple developers can add migrations independently; conflicts in migration files are explicit.

How migrations work:

  1. Migration files live in database/migrations/, named YYYY_MM_DD_HHMMSS_description.php.
  2. php artisan migrate reads all migrations not yet in the migrations table.
  3. Runs each migration's up() method.
  4. Records the migration name and batch number in the migrations table.
  5. migrate:rollback finds the latest batch and runs each migration's down() method.

The migrations table: Created by php artisan migrate on first run. Stores migration (filename), batch (integer). All migrations in one migrate run share the same batch number.

Schema facade: Illuminate\Support\Facades\Schema. Used inside migrations to create/modify tables.

Code Example

php
<?php
// database/migrations/2024_01_15_120000_create_orders_table.php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    // up() — apply the change
    public function up(): void
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->id();                    // BIGINT UNSIGNED AUTO INCREMENT PRIMARY KEY
            $table->foreignId('user_id')
                  ->constrained()
                  ->onDelete('cascade');
            $table->decimal('total', 10, 2);
            $table->string('status', 20)->default('pending');
            $table->timestamps();            // created_at, updated_at
        });
    }

    // down() — undo the change (for rollback)
    public function down(): void
    {
        Schema::dropIfExists('orders');
    }
};

// Running migrations
// php artisan migrate                 → run all pending migrations
// php artisan migrate --force         → run in production (bypasses prompt)
// php artisan migrate:status          → show which migrations have run
// php artisan migrate:rollback        → roll back last batch
// php artisan migrate:rollback --step=3  → roll back 3 batches
// php artisan migrate:reset           → roll back ALL migrations
// php artisan migrate:fresh           → drop all tables + re-migrate (dev only!)
// php artisan migrate:fresh --seed    → fresh migrate + seed
// php artisan migrate:refresh         → rollback all + re-migrate