Forked from NBZ4live/2018_02_07_101510_migrate_to_utf8mb4.php
Last active
April 16, 2025 16:35
-
-
Save hrsa/7a45420329e745315ee02a08ddbf3d41 to your computer and use it in GitHub Desktop.
Laravel migration to migrate the database from utf8 to utf8mb4 (exclude views and char() columns and keep default values)
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\Database\Migrations\Migration; | |
return new class extends Migration { | |
public function up(): void | |
{ | |
$this->migrateCharsetTo('utf8mb4', 'utf8mb4_unicode_ci'); | |
} | |
public function down(): void | |
{ | |
$this->migrateCharsetTo('utf8', 'utf8_unicode_ci'); | |
} | |
protected function migrateCharsetTo($charset, $collation): void | |
{ | |
$defaultConnection = config('database.default'); | |
$databaseName = config("database.connections.{$defaultConnection}.database"); | |
// Change default charset and collation | |
DB::unprepared("ALTER SCHEMA {$databaseName} DEFAULT CHARACTER SET {$charset} DEFAULT COLLATE {$collation};"); | |
// Get the list of all tables | |
$tableNames = DB::table('information_schema.tables') | |
->where('table_schema', $databaseName) | |
->where('table_type', '=', 'BASE TABLE') | |
->get(['TABLE_NAME']) | |
->pluck('TABLE_NAME'); | |
// Iterate through the list and alter each table | |
foreach ($tableNames as $tableName) { | |
DB::unprepared("ALTER TABLE {$tableName} CONVERT TO CHARACTER SET {$charset} COLLATE {$collation};"); | |
} | |
// Get the list of all columns in the active db that have a collation | |
$columns = DB::table('information_schema.columns') | |
->where('table_schema', $databaseName) | |
->whereIn('table_name', $tableNames) | |
->whereNotNull('COLLATION_NAME') | |
->get(); | |
// Iterate through the list and alter each column | |
foreach ($columns as $column) { | |
$tableName = $column->TABLE_NAME; | |
$columnName = $column->COLUMN_NAME; | |
$columnType = $column->COLUMN_TYPE; | |
// Skip strange columns with char() type | |
if (strpos($columnType, "char(") === 0) { | |
continue; | |
} | |
// Check for default value in nullable and not nullable columns | |
if ($column->IS_NULLABLE == 'NO') { | |
if ($column->COLUMN_DEFAULT !== null) { | |
$default = "DEFAULT $column->COLUMN_DEFAULT"; | |
} else { | |
$default = 'NOT NULL'; | |
} | |
} elseif ($column->COLUMN_DEFAULT !== null) { | |
$default = "DEFAULT $column->COLUMN_DEFAULT"; | |
} else { | |
$default = 'DEFAULT NULL'; | |
} | |
$sql = "ALTER TABLE {$tableName} | |
CHANGE `{$columnName}` `{$columnName}` | |
{$columnType} | |
CHARACTER SET {$charset} | |
COLLATE {$collation} | |
{$default}"; | |
DB::unprepared($sql); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment