Master Laravel Migrations: From Creation to Rollback and Advanced Schema Operations

This guide explains how Laravel migrations act as database version control, covering generation, structure, execution, table and column creation, modifiers, indexes, foreign keys, and rollback strategies with practical Artisan commands and code examples.

Laravel Tech Community
Laravel Tech Community
Laravel Tech Community
Master Laravel Migrations: From Creation to Rollback and Advanced Schema Operations

Introduction

Database migrations in Laravel work like version control for your schema, letting teams edit and share table structures safely. The Schema facade provides a unified API for all supported databases.

Generating Migrations

Use the Artisan command make:migration to create a new migration file in database/migrations. The filename includes a timestamp to preserve execution order. Options: --create=table_name – creates the table when the migration runs. --table=table_name – targets an existing table. --path=custom_path – stores the file in a custom directory relative to the project root.

php artisan make:migration create_users_table

Migration Structure

Each migration class contains two methods: up() – adds tables, columns, indexes, etc. down() – reverses the actions performed in up().

Both methods use the Schema builder to define changes.

Running Migrations

Execute all pending migrations with: php artisan migrate In production, Laravel asks for confirmation before destructive operations; use --force to bypass the prompt. php artisan migrate --force Rollback commands: php artisan migrate:rollback – rolls back the last batch. php artisan migrate:rollback --step=5 – rolls back the last five batches. php artisan migrate:reset – rolls back all migrations. php artisan migrate:refresh – resets and re‑runs all migrations. php artisan migrate:fresh – drops all tables and runs migrations anew.

Creating Tables

Use

Schema::create('table_name', function (Blueprint $table) { ... })

. Inside the closure you define columns with methods such as increments('id'), string('name'), timestamps(), etc.

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateFlightsTable extends Migration {
    public function up() {
        Schema::create('flights', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('airline');
            $table->timestamps();
        });
    }
    public function down() {
        Schema::drop('flights');
    }
}

Renaming and Dropping Tables

Rename with Schema::rename($from, $to) and drop with Schema::drop('table') or Schema::dropIfExists('table'). When renaming tables that have foreign keys, give the foreign keys explicit names to avoid broken references.

Columns

Creating columns uses the table method:

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('email');
});

Laravel supports a wide range of column types (bigIncrements, integer, string, text, json, uuid, geometry, etc.). See the original list for the full set.

Column Modifiers

Modifiers adjust column behavior, e.g. $table->string('email')->nullable();. Common modifiers include: ->after('other_column') – place column after another (MySQL). ->autoIncrement() – make an integer auto‑increment. ->charset('utf8') – set character set (MySQL). ->collation('utf8_unicode_ci') – set collation. ->comment('note') – add a comment (MySQL). ->default($value) – set default value. ->first() – place column first (MySQL). ->nullable() – allow NULL. ->storedAs($expression) – create a stored generated column (MySQL). ->unsigned() – make integer unsigned. ->useCurrent() – set CURRENT_TIMESTAMP as default for timestamps. ->virtualAs($expression) – create a virtual generated column (MySQL).

Modifying Columns

To change an existing column you must install the doctrine/dbal package: composer require doctrine/dbal Then use the change() method:

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->change();
    $table->string('email')->nullable()->change();
});

Renaming a column uses renameColumn('old', 'new') (requires doctrine/dbal). Enum columns cannot be renamed.

Dropping Columns

Remove a column with dropColumn('column'). Multiple columns can be passed as an array. SQLite requires the doctrine/dbal package for column drops.

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('votes');
    $table->dropColumn(['votes', 'avatar', 'location']);
});

Indexes

Indexes are created via methods on the Blueprint instance: $table->primary('id') – primary key. $table->unique('email') – unique index. $table->index('state') – regular index. $table->spatialIndex('location') – spatial index (except SQLite).

Composite indexes accept an array of columns, e.g. $table->index(['account_id','created_at']).

Custom index names can be supplied as a second argument.

When using older MySQL (< 5.7.7) or MariaDB (< 10.2.2) you may need to set a default string length in AppServiceProvider:

use Illuminate\Support\Facades\Schema;
public function boot() {
    Schema::defaultStringLength(191);
}

Dropping Indexes

Indexes are removed by name, e.g. $table->dropPrimary('users_id_primary') or $table->dropUnique('users_email_unique'). Passing an array of columns lets Laravel generate the appropriate name automatically.

Foreign Keys

Define foreign key constraints with the foreign method:

Schema::table('posts', function (Blueprint $table) {
    $table->integer('user_id')->unsigned();
    $table->foreign('user_id')
          ->references('id')
          ->on('users')
          ->onDelete('cascade');
});

Drop a foreign key with dropForeign('posts_user_id_foreign') or by passing the column array.

Schema::table('posts', function (Blueprint $table) {
    $table->dropForeign(['user_id']);
});

Foreign key constraints can be globally enabled or disabled:

Schema::enableForeignKeyConstraints();
Schema::disableForeignKeyConstraints();
Laravel migrations illustration
Laravel migrations illustration
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PHPLaravelArtisanSchema BuilderDatabase Migrations
Laravel Tech Community
Written by

Laravel Tech Community

Specializing in Laravel development, we continuously publish fresh content and grow alongside the elegant, stable Laravel framework.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.