Check If a Column Exists in Laravel Migration File

Viewed 60013

Already I have a table name table_one. Now I want to add two more columns to it. Everything works fine so far. But in my method, I want to check a column exists or not in my table like dropIfExists('table').

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::table('table_one', function (Blueprint $table) {
        $table->string('column_one')->nullable();
        $table->string('column_two')->nullable();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::table('table_one', function (Blueprint $table) {
        // in here i want to check column_one and column_two exists or not
        $table->dropColumn('column_one');
        $table->dropColumn('column_two');
    });
}
5 Answers

You need something just like this

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

You could make your own 'dropColumnIfExists()' function that checks the column existence then drop it:

function myDropColumnIfExists($myTable, $column)
{
    if (Schema::hasColumn($myTable, $column)) //check the column
    {
        Schema::table($myTable, function (Blueprint $table)
        {
            $table->dropColumn($column); //drop it
        });
    }

}

And use it on 'down()' function like this:

public function down()
{
    myDropColumnIfExists('table_one', 'column_two');
    myDropColumnIfExists('table_one', 'column_one');
}

For dynamically checking your table column you can try something like this:

public function dropIfExists($table, $column)
{
    if (Schema::hasColumn($table, $column)) //check the column
    {
        Schema::table($table, function (Blueprint $table) use ($column)
        {
            $table->dropColumn($column); //drop it
        });
    }

}

If you really want it inside the Schema::table closure, which is the only neat way to do it... you would either need to add a couple of methods to Blueprint, or use this boilerplate inside every migration... it's not pretty, but once it's there you can define as many conditional add and drop's as you like, using only 1 line each.

return new class extends Migration {
    public function up() {

        Schema::table('tblAnimal', function (Blueprint $table) {
            $exists = function (string $column) use ($table) {
                return (Schema::hasColumn($table->getTable(), $column));
            };
            $addUnlessExists = function (string $type, string $name, array $parameters = [])
                use ($table, $exists) {
                    return $exists($name) ? null : $table->addColumn($type, $name, $parameters);
                };
            $dropIfExists = function (string $column) use ($table, $exists) {
                return $exists($column) ? $table->dropColumn($column) : null;
            };

            $dropIfExists('column_name');
            $addUnlessExists('integer', 'int_column');
            # ...
        });

Just break the schema up into two calls

public function up()
{
    Schema::table('table_one', function (Blueprint $table) {
        $table->dropColumn(['column_one', 'column_two']);
    });

    Schema::table('table_one', function (Blueprint $table) {
        $table->string('column_one')->nullable();
        $table->string('column_two')->nullable();
    });
}
Related