Laravel 5.1 Unknown database type enum requested
While running php artisan migrate, I got the following error
[Doctrine\DBAL\DBALException]
Unknown database type enum requested, Doctrine\DBAL\Platforms\MySqlPlatform may not support it.
How to resolve this issue.
Code:
public function up() {
Schema::table('blogs', function (Blueprint $table) {
$table->string('wordpress_id')->nullable();
$table->string('google_blog_id')->nullable()->change();
});
}
Solution 1:
It is a known issue as stated in Laravel 5.1 documentation.
Note: Renaming columns in a table with a
enum
column is not currently supported.
It happens when you have a enum
column in your database table. Whether you are trying to rename another column, or change another column to nullable
, this bug will appear. It's an issue with Doctrine\DBAL
.
An easy fix for this is to just add this constructor method in your database migration file.
public function __construct()
{
DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
}
This will map all the ENUM
columns to VARCHAR()
, and the column will accept any string.
This worked for me on Laravel 5.1 and Laravel 5.3. I hope this bug can be fixed soon.
Credit to @Gmatkowski's answer at https://stackoverflow.com/a/32860409/1193201
Solution 2:
The official Laravel 5.1 documentation states:
Note: Renaming columns in a table with a enum column is not currently supported.
It doesn't matter if you're trying to change another column, if the table contains a enum
anywhere it won't work. It's a Doctrine DBAL issue.
As a workaround you could either drop the column and add a new one (column data will be lost):
public function up()
{
Schema::table('users', function(Blueprint $table)
{
$table->dropColumn('name');
});
Schema::table('users', function(Blueprint $table)
{
$table->text('username');
});
}
or use a DB statement:
public function up()
{
DB::statement('ALTER TABLE projects CHANGE slug url VARCHAR(200)');
}
public function down()
{
DB::statement('ALTER TABLE projects CHANGE url slug VARCHAR(200)');
}
Source: https://github.com/laravel/framework/issues/1186
Solution 3:
I get rid of this problem by creating a new Migration Class and making my migrations extending from it. Maybe there are multiple ways to make it more "standard" but this is just a very simple case which works perfectly for our team.
use Doctrine\DBAL\Types\{StringType, Type};
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\{DB, Log};
/**
* Class ExtendedMigration
* Use it when the involved table(s) has enum type column(s)
*/
class ExtendedMigration extends Migration
{
/**
* ExtendedMigration constructor.
* Handle Laravel Issue related with modifying tables with enum columns
*/
public function __construct()
{
try {
Type::hasType('enum') ?: Type::addType('enum', StringType::class);
Type::hasType('timestamp') ?: Type::addType('timestamp', DateTimeType::class);
} catch (\Exception $exception) {
Log::info($exception->getMessage());
}
}
}
Then as explained before just extend your migration from it
class SampleMigration extends ExtendedMigration
{
public function up()
{
Schema::create('invitations', function (Blueprint $table) {
...
$table->enum('status', ['sent', 'consumed', 'expired'])->default('sent');
...
});
}
public function down()
{
Schema::dropIfExists('invitations');
}
}
Solution 4:
You should not use enum at all. Even with laravel 5.8, problem is not resolved.
Thank's to everyone who reminded that
The official Laravel 5.1 documentation states:
Note: Renaming columns in a table with a enum column is not currently supported.
Plus you will have the same problem when adding available options into enum
column declaration.
It brings me to a conclusion that You should use enum with care. or even You should not use enum at all.
I cannot vote up any answer that offer to replace enum with string. NO, you need to create a lookup table and replace enum with unsignedInteger
as a foreign key
.
It is a lot of work and you'll be upset doing it without previous unit-test coverage, but this is a right solution.
You may be even fired for doing this correctly, because it is taking too long, but, don't worry, you'll find a better job. :)
Here is an example of how difficult would it be adding available options into enum
column declaration
say you have this:
Schema::create('blogs', function (Blueprint $table) {
$table->enum('type', [BlogType::KEY_PAYMENTS]);
$table->index(['type', 'created_at']);
...
and you need to make more types available
public function up(): void
{
Schema::table('blogs', function (Blueprint $table) {
$table->dropIndex(['type', 'created_at']);
$table->enum('type_tmp', [
BlogType::KEY_PAYMENTS,
BlogType::KEY_CATS,
BlogType::KEY_DOGS,
])->after('type');
});
DB::statement('update `blogs` as te set te.`type_tmp` = te.`type` ');
Schema::table('blogs', function (Blueprint $table) {
$table->dropColumn('type');
});
Schema::table('blogs', function (Blueprint $table) {
$table->enum('type', [
BlogType::KEY_PAYMENTS,
BlogType::KEY_CATS,
BlogType::KEY_DOGS,
])->after('type_tmp');
});
DB::statement('update `blogs` as te set te.`type` = te.`type_tmp` ');
Schema::table('blogs', function (Blueprint $table) {
$table->dropColumn('type_tmp');
$table->index(['type', 'created_at']);
});
}
Solution 5:
You can either use the above suggestions or can add the below code to your migration file...
public function up()
{
DB::connection()->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
Schema::table('<YOUR_TABLE>', function (Blueprint $table) {
//YOUR CHANGES HERE
}
}