How can indexes be checked if they exist in a Laravel migration?

19,085

Solution 1

Using "doctrine-dbal" that Laravel uses is better solution:

Schema::table('persons', function (Blueprint $table) {
    $sm = Schema::getConnection()->getDoctrineSchemaManager();
    $indexesFound = $sm->listTableIndexes('persons');

    if(array_key_exists("persons_body_unique", $indexesFound))
        $table->dropUnique("persons_body_unique");
});

Solution 2

The mysql query

SHOW INDEXES FROM persons

will give you back all of the indexes on the table, however it includes additional info other than just the names. In my setup, the column containing the name is called Key_name so lets get a collection of key names

collect(DB::select("SHOW INDEXES FROM persons"))->pluck('Key_name')

And since its a collection you can use contains so finally we have:

if (collect(DB::select("SHOW INDEXES FROM persons"))->pluck('Key_name')->contains('persons_body_unique')) {
        $table->dropUnique('persons_body_unique');
}

Solution 3

In the simple form, you can do this

Schema::table('persons', function (Blueprint $table) {
    $index_exists = collect(DB::select("SHOW INDEXES FROM persons"))->pluck('Key_name')->contains('persons_body_unique');
    if ($index_exists) {
        $table->dropUnique("persons_body_unique");
    }
})
Share:
19,085

Related videos on Youtube

Oladipo
Author by

Oladipo

Updated on June 30, 2020

Comments

  • Oladipo
    Oladipo almost 4 years

    Trying to check if a unique index exists on a table when preparing a migration, how can it be achieved?

    Schema::table('persons', function (Blueprint $table) {
        if ($table->hasIndex('persons_body_unique')) {
            $table->dropUnique('persons_body_unique');
        }
    })
    

    Something that looks like the above. (apparently, hasIndex() doesn't exist)

  • Roland
    Roland almost 6 years
    This shouldn't be the accepted answer as it is not cross-dbms ("portable", not vendor-specific). The answer by @admirko is much more better as it goes over Laravel's underlaying Doctrine layer and not over a "native query".
  • Roland
    Roland almost 6 years
    As mentioned above, this should be the right answer as it goes over Laravel's Doctrine and does not use a native query.
  • Filip Filipovic
    Filip Filipovic over 5 years
    I can confirm this works on 5.2, after i installed the doctrine-dbal package from the repo.
  • RyanNerd
    RyanNerd about 5 years
    Be aware that listTableIndexes() will return the name of indexes in lower case.
  • JKOlaf
    JKOlaf over 3 years
    Minor add to make copy/paste for other migrations in your future you can use the $table object to get the name. $indexesFound = $sm->listTableIndexes($table->getTable());