Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Migrations that cause error don't rollback

I've found that, while building up my database schema in Laravel, that failed migrations don't rollback, which kind of makes migrations pointless.

For example, I have this migration:

Schema::create('accounts', function(Blueprint $table)
{
    $table->increments('act_id');

    $table->string('act_name', 50)->unique();
    $table->boolean('act_active')->default(1);
    $table->unsignedInteger('act_type');
    $table->unsignedInteger('act_businesstype')->default(1);

    $table->timestamps();
});

Schema::table('accounts', function($table)
{
    $table->foreign('act_businesstype')->references('bst_id')->on('businesstypes');
});

Anyway, if I run that migration, the table gets created just fine, but the foreign key fails and I get an error. That's fine. I should get an error. BUT, common sense has me assuming the following:

  1. Since the migration failed, the changes should automatically rollback. Well, they don't.

Okay, so

  1. I should call migrate:rollback to undo those changes. Well, there is no record of that migration happening so I end up rolling back the one that occurred before.

Am I doing something wrong here? The only way I've figured out how to "undo" a failed migration is to actually go into the database and drop the table. This is extremely frustrating when working on a complex schema where I'm going back and forth fixing errors.

So, I guess now that I've had my little rant, my question is:

How do I rollback a migration that throws an error?

like image 985
Troncoso Avatar asked Oct 11 '14 02:10

Troncoso


2 Answers

One solution is to execute your migrations from within a transaction, so that if an error occurs mid-migration, nothing gets committed and the whole transaction gets rolled back. Antonio Carlos Ribeiro has written a great class that handles this process neatly; see his description of the process here as well as the finished migration class on GitHub.

Once you've installed his class, create your migrations so that they extend the new Migration class, and call migrateUp() and migrateDown() in place of up() and down():

class CreateAccountsTable extends PragmaRX\Support\Migration {

    protected function migrateUp()
    ...

...and enjoy not having to manually fix a botched migration again!

like image 99
damiani Avatar answered Nov 03 '22 17:11

damiani


Coming back to this question years later and knowing much more about how databases work now:

There is no way for a migration to "automatically rollback". Schema changes cannot be performed in transactions. Only INSERTS, UPDATES, and DELETES can be rolled back.

In order for this to function correctly, there would need to be an equivalent "drop" script that runs in the event of an error to revert the schema change

like image 42
Troncoso Avatar answered Nov 03 '22 15:11

Troncoso