DEV Community

Recca Tsai
Recca Tsai

Posted on • Originally published at recca0120.github.io

3 Laravel Migration Pitfalls and How to Fix Them

Originally published at recca0120.github.io

I recently hit several pitfalls when using migration:rollback. Here are the common mistakes and how to catch them early with tests.

Common Mistakes

Adding and dropping columns in the same closure

// Bad
Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('old_column');
    $table->string('new_column');
});

// Good — split into two closures
Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('old_column');
});

Schema::table('users', function (Blueprint $table) {
    $table->string('new_column');
});
Enter fullscreen mode Exit fullscreen mode

Dropping an index and column at the same time

// Bad
Schema::table('users', function (Blueprint $table) {
    $table->dropIndex('users_old_column_index');
    $table->dropColumn('old_column');
});

// Good — drop the index first, then the column
Schema::table('users', function (Blueprint $table) {
    $table->dropIndex('users_old_column_index');
});

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('old_column');
});
Enter fullscreen mode Exit fullscreen mode

Dropping multiple columns must be in a single call

// Bad
Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('old_column');
    $table->dropColumn('old_column2');
});

// Good
Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('old_column', 'old_column2');
});
Enter fullscreen mode Exit fullscreen mode

How to Automatically Validate Migrations

Running migration:rollback on a production database to test is too risky. A safer approach is to use PHPUnit + SQLite in-memory.

1. Configure phpunit.xml

Add these two lines in the <php> block:

<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
Enter fullscreen mode Exit fullscreen mode

2. Write a test

It doesn't need to be complex -- just make sure the migration runs without errors:

namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;

class MigrationTest extends TestCase
{
    use DatabaseMigrations;

    public function testMigrationRunsSuccessfully()
    {
        $this->assertTrue(true);
    }
}
Enter fullscreen mode Exit fullscreen mode

Run vendor/bin/phpunit. If any migration has a problem, it will fail immediately. This way you can catch broken migrations right away every time you make changes.

Top comments (0)