Migration – down: check if table has column

One of the problem with database migrations in Laravel is developers rarely actually test “down” migrations – even when testing we usually re-generate the whole schema from scratch instead of launching down() functions. Therefore I would advice to check something before doing down migrations.

Common example in my experience – adding a new column to existing table. In up() function we’re adding the column, and in down() we’re removing it. Something like this:

    public function up()
    {
        Schema::table('users', function (Blueprint $table)
        {
            $table->string('phone')->nullable()->after('email');
        });
    }

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

Now, if we’re doing migrate:rollback and for whatever reason that column doesn’t exist in the table, it will throw an error. So a proper way is to add an if-statement.

    public function down()
    {
        if (Schema::hasColumn('users', 'phone'))
        {
            Schema::table('users', function (Blueprint $table)
            {
                $table->dropColumn('phone');
            });
        }
    }

Similarly you can add if-statements like this in other parts of your migrations, it just depends on your level of “paranoia” and the odds that someone would change the database structure outside the migrations scripts – for example, manually via phpMyAdmin or Sequel Pro clients.

Like our articles?
Check out our Laravel online courses!

4 COMMENTS

  1. If you’re using Laravel’s “Illuminate\Foundation\Testing\DatabaseMigrations” helper trait, it migrates down after every test!

    By adding if statements on the “Down” migrations you’re promoting the ability to edit the database outside of the migrations – something that I’d rather avoid. What do you think?

    Keep the tips coming!

    • Thanks for the opinion Michael, I do agree that it’s kind of promoting the wrong behavior, it was just my experience while working in a team where a lot of people had access to phpMyAdmin and it was a mess at times. But if you do all the things in a right way, then you’re right – it shouldn’t need if-statements. In a perfect world 🙂

  2. Migrations rollback part actually exists, because of production website upgrading, there is no need to use it in dev environments.

    • This is exactly the point. Test your work before it goes on production.
      If you have never tested your rollback behaviour and then run it on production you can end up doing a partial migration before it fails. This has happened to me on a dev environment where you end up stuck where you can’t migrate or rollback and the structure is left midway between two migrations in an unstable state.
      This is recoverable by removing the offending migration row from the migrations table and altering the tables directly to move you from the current state to where you need to be.
      Conditional statements are used throughout your codebase to prevent even the most unlikely events from crashing your site so why not use it here too which has the potential to bring down the whole site.

LEAVE A REPLY

Please enter your comment!
Please enter your name here