Skip to content

Chapter 2.3: Database Migrations

Time to learn: 50 minutes


1. Migrations: Building the Space Station

Migrations in Laravel are a version control system for your database.

Imagine that you:

  1. 🏗️ Create a blueprint for the station (the create_planets_table migration)
  2. 🚀 Deploy the modules (run the migrations)
  3. 🔧 Upgrade the structure (new migrations)
  4. ⏪ Can roll back to a previous version (rollback)

💡 Important: Migrations allow a team to work in a coordinated way—like engineers on different continents building the ISS!


2. Running Migrations

After creating the migration in Chapter 2.2, execute:

php artisan migrate

Output in the terminal:

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (25.12ms)
Migrating: 2014_10_12_100000_create_password_reset_tokens_table
Migrated:  2014_10_12_100000_create_password_reset_tokens_table (18.07ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (21.33ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (30.45ms)
Migrating: 2025_08_04_000000_create_planets_table
Migrated:  2025_08_04_000000_create_planets_table (15.67ms)  # Your table!

Checking in pgAdmin 4:

  1. Open the space_api database → Schemas → Tables
  2. Make sure the following have appeared: - planets - users - password_reset_tokens

3. Rolling Back Migrations: Emergency Return

If you need to correct the structure:

php artisan migrate:rollback  # Roll back the last batch of migrations
php artisan migrate:reset    # Completely roll back all migrations

  • php artisan migrate:freshthe most useful command in development! It drops all tables and re-runs all migrations.
  • php artisan migrate:fresh --seed — does the same as fresh, but also runs seeders immediately after migrating. This is the command for a complete "rebuild" of the database from scratch.

Usage Scenario:

# Step 1: Realized there's an error in the migration. Completely rebuild the database.
php artisan migrate:fresh
# Step 2: Edit the migration file
# Step 3: Rebuild the database again with the corrected migration
php artisan migrate:fresh


4. Adding New Fields: Upgrading the Station

Example: Let's add an is_habitable field.

Step 1: Create a new migration

php artisan make:migration add_is_habitable_to_planets_table

Step 2: Edit the file database/migrations/..._add_is_habitable_to_planets_table.php

<?php
public function up()
{
    Schema::table('planets', function (Blueprint $table) {
        $table->boolean('is_habitable')
              ->default(false);
    });
}

public function down()
{
    Schema::table('planets', function (Blueprint $table) {
        $table->dropColumn('is_habitable');
    });
}

Step 3: Run the update

php artisan migrate


5. Seeding the Database: The First Planets

We create a Seeder—a script for generating test data.

Step 1: Generate the seeder

php artisan make:seeder PlanetSeeder

Step 2: Edit database/seeders/PlanetSeeder.php

<?php
use App\Models\Planet; // Import the Planet model - you'll get an error without it!


class PlanetSeeder extends Seeder
{
    public function run()
    {
        Planet::create([
            'name' => 'Earth',
            'description' => 'A blue planet with diverse life',
            'size_km' => 12742,
            'solar_system' => 'Solar System',
            'image_url' => 'https://example.com/earth.jpg',
            'is_habitable' => true
        ]);

        Planet::create([
            'name' => 'Mars',
            'description' => 'The red planet, a target for future colonization',
            'size_km' => 6779,
            'solar_system' => 'Solar System',
            'is_habitable' => false
        ]);
    }
}

Step 3: Register the seeder in database/seeders/DatabaseSeeder.php

<?php
public function run()
{
    $this->call([
        PlanetSeeder::class
    ]);
}

Step 4: Run the seeder

php artisan db:seed


6. Working with PostgreSQL: Specifics

Data Type Peculiarities:

Feature PostgreSQL MySQL Laravel Comment
Boolean Type boolean (true true/false) tinyint(1) (stores 0/1) $table->boolean('...') works for both
JSON jsonb (binary, indexable) json (text-based) $table->jsonb('...') - very powerful in PG
Arrays text[], integer[] (native arrays) No (emulated via JSON or strings) $table->array('...') (PG exclusive)
Column Order Cannot be controlled (after() doesn't work) Can be controlled (after()) Laravel abstracts this, but you need to know the limitation

Example of creating an index:

// In a migration
$table->index('solar_system');


7. Verifying Data in psql

You can use any graphical client and select space_api to view it.

If using the console:

psql -U postgres -d space_api
# The terminal may ask for the password you set during the PostgreSQL installation.
SELECT * FROM planets;

In either case, the output should be as follows:

id name description size_km solar_system image_url is_habitable
1 Earth A blue planet with diverse life 12742 Solar System ... true
2 Mars The red planet, a target for future colonization 6779 Solar System null false

Review Quiz

1. The command to run migrations is:

2. How do you roll back the last migration?

3. Seeders are used for:

4. The method for adding a column to an existing table is:

5. Where are seeders registered?


🚀 Chapter Summary:

You have mastered "building cosmic infrastructure":

  • ✅ Created and ran migrations
  • 🔧 Upgraded the table structure
  • 🌍 Populated the DB with the first planets
  • ⚙️ Learned to work with PostgreSQL

Your universe has gained its first worlds! Now you can move on to creating API interfaces to manage the planets.

📌 Checkpoint:

  1. Run php artisan tinker
  2. Execute App\Models\Planet::all()
  3. Make sure you see Earth and Mars