Created
August 8, 2017 01:35
-
-
Save Razoxane/3bc74900b4eb5c983eb0927fa13b95f5 to your computer and use it in GitHub Desktop.
Laravel - Create Index If Not Exists / Drop Index If Exists
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Illuminate\Support\Facades\Schema; | |
use Illuminate\Database\Schema\Blueprint; | |
use Illuminate\Database\Migrations\Migration; | |
class LaravelConditionalIndexMigration extends Migration | |
{ | |
/** | |
* Run the migrations. | |
* | |
* @return void | |
*/ | |
public function up() | |
{ | |
Schema::table('tablename', function (Blueprint $table) { | |
$sm = Schema::getConnection()->getDoctrineSchemaManager(); | |
$doctrineTable = $sm->listTableDetails('tablename'); | |
if (! $doctrineTable->hasIndex('singlecolumnindexname')) { | |
$table->index('column1', 'singlecolumnindexname'); | |
} | |
if (! $doctrineTable->hasIndex('multicolumnindexname')) { | |
$table->index(['column2', 'column3'], 'multicolumnindexname'); | |
} | |
}); | |
} | |
/** | |
* Reverse the migrations. | |
* | |
* @return void | |
*/ | |
public function down() | |
{ | |
Schema::table('tablename', function (Blueprint $table) { | |
$sm = Schema::getConnection()->getDoctrineSchemaManager(); | |
$doctrineTable = $sm->listTableDetails('tablename'); | |
if ($doctrineTable->hasIndex('singlecolumnindexname')) { | |
$table->dropIndex('singlecolumnindexname'); | |
} | |
if ($doctrineTable->hasIndex('multicolumnindexname')) { | |
$table->dropIndex('multicolumnindexname'); | |
} | |
}); | |
} | |
} |
I'm glad I found this, because that's exactly what I was looking for! Thanks for the comments!
I made a portable/reuseable solution for it (app/Domain/Migration/MigrationUtil.php
):
<?php
declare(strict_types=1);
namespace App\Domain\Migration;
use Doctrine\DBAL\Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class MigrationUtil
{
/**
* INFO: https://gist.github.com/Razoxane/3bc74900b4eb5c983eb0927fa13b95f5
*
* @throws Exception
*/
public static function hasIndex(string $tableName, string $indexName): bool
{
$doctrineSchemaManager = Schema::getConnection()->getDoctrineSchemaManager();
return $doctrineSchemaManager->introspectTable($tableName)->hasIndex($indexName);
}
}
usage:
<?php
declare(strict_types=1);
use App\Domain\Migration\MigrationUtil;
use Illuminate\Database\Migrations\Migration;
return new class() extends Migration {
public function up(): void
{
Schema::table('users', static function ($table) {
if (MigrationUtil::hasIndex('users', 'unique_email')) {
$table->dropUnique('unique_email');
}
if (!MigrationUtil::hasIndex('users', 'users_email_unique')) {
$table->unique('email');
}
});
}
};
Thanks! Great stuff 🙇♂️ 💯
In Laravel 11 Symfony's DBAL has been replaced by Laravel's native classes so above solutions does not work anymore. Here's the working dropIndexIfNotExists
for Laravel 11.
<?php
namespace App\Traits;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
trait MigrationIndex
{
public function dropIndexIfExist(string $tableName, string $indexName): void
{
$indexes = Schema::getIndexes($tableName);
foreach ($indexes as $index) {
if ($index['name'] === $indexName) {
Schema::table($tableName, static function (Blueprint $table) use ($indexName) {
$table->dropIndex($indexName);
});
}
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I don't know in which version it appeared, but now there is a replacement :
introspectTable()