98

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();
    });
}
8
  • Please post the schema you're trying to migrate. Commented Oct 15, 2015 at 6:51
  • public function up() { Schema::table('blogs', function (Blueprint $table) { $table->string('wordpress_id')->nullable(); $table->string('google_blog_id')->nullable()->change(); }); } Commented Oct 15, 2015 at 6:54
  • Does your table contain a enum column? Commented Oct 15, 2015 at 7:00
  • yeah.. It has one enum type field. In another migration(but this migration is working fine), I have the following 'DB::statement('ALTER TABLE blogs MODIFY type enum("wordpress","blogger") NULL;');' Commented Oct 15, 2015 at 7:03
  • 1
    Renaming columns in a table with a enum column is not currently supported in Laravel. Doesn't matter if you are trying to change another column. If the table contains an enum it won't work. I'm afraid that you will have to change that manually somehow, or try some rather ugly hacks or workarounds. Commented Oct 15, 2015 at 7:07

10 Answers 10

156

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::getDoctrineConnection()->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

Sign up to request clarification or add additional context in comments.

4 Comments

This should be the accepted answer! Thank you @Xeleon
Will this change the type mapping globally, or just for the migration it is specified in? And if it is global, will this have any other side effects? To be sure I used the old Laravel 4 way, which does also work (laraveldaily.com/…).
I had to add that line to AppServiceProvider::boot() in order to make it work.
Thanks that worked. I just ran into this on 6.x and I see the known issue persists to 8.x as of now
130

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

6 Comments

Thanks for the solution, drop column isn't always possible, so manual alter should do it
You don't need the Schema wrap around the DB::statement if you're not using $table
What a bummer! I was trying to update a column not related with the enum and this is sending the Exception. Ok, I guess the DB::statement is the best option here. Thx.
I'd prefer the second approach as first one would affect data as it would drop and recreate columns. But the second approach will only affect table structure.
What the heck is wrong with doctrine/dbal that they cannot allow you to do something that is very easily done with a SQL query?
|
9

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');
    }
}

2 Comments

where to put this ExtendedMigration? I successfully add the type directly to the up function on a normal migration, but I am curious where you put the ExtendedMigration class
@Dika, Depending on your type of project, if you are building a library maybe makes sense to put it in the database folder, in my case we have a regular Laravel project and I have it under a helpers folder app/Helpers/ExtendedMigration.php and of course, it gets the namespace App\Helpers
8

I had the same problem, I could solve it in Laravel 10.x in the following ways:

Option 1: Using native schema operations

You have to call Schema::useNativeSchemaOperationsIfPossible() method within the boot method of your App\Providers\AppServiceProvider class or within your migrations files to be able to use native schema operations.

References:

Option 2: Adding doctrine type mapping

Add this constructor method in your database migration file.

use Doctrine\DBAL\Types\StringType;
use Doctrine\DBAL\Types\Type;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

....

public function __construct()
{
    if (!Type::hasType('enum')) {
        Type::addType('enum', StringType::class);
    }

    DB::getDoctrineConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
}

Option 3: Using DB statements

use Illuminate\Support\Facades\DB;

...

public function up()
{
    DB::statement("ALTER TABLE `table_name` CHANGE `column_name` `column_name` ENUM('option1', 'option2', 'option2') DEFAULT 'option1';");
}

Reference

Comments

7

Laravel: 5.8, 6, 7, 8

use Doctrine\DBAL\Types\StringType;
use Doctrine\DBAL\Types\Type;
use Illuminate\Support\Facades\DB;

    public function __construct()
    {
        if (! Type::hasType('enum')) {
            Type::addType('enum', StringType::class);
        }
        // For point types
        // DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('point', 'string');
        DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
    }

4 Comments

What is the Type class?
I updated the code: Doctrine\DBAL\Types\Type
This answer from years previous also includes the registerDoctrineTypeMapping() command by itself. What does the call to addType() do to improve on that answer?
Probably, I will not have the chance to test it. Let us know
6

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']);
    });
}

Comments

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
}    
    }

3 Comments

tried this on laravel 7.x. still error, but thanks for the idea
It works for me on 8.x. I have a different case though, I am retrieving a schema listing for a given table
This is just a copy from the most upvoted answer above.
3

A real dirty solution, that gets the job done none the less would be to

update Doctrine/DBAL/Schema/MySqlSchemaManager.php 

by ading these lines just above line 113

$this->_platform->registerDoctrineTypeMapping('enum', 'string');
$type = $this->_platform->getDoctrineTypeMapping($dbType);

Beware that updating vendor files directly is not advisable because in the event the vonder chooses to update the plugin, you changes could be overwritten

2 Comments

I'm doing it, but It doesn't work. protected function _getPortableDatabaseDefinition($database) { $this->_platform->registerDoctrineTypeMapping('enum', 'string'); $type = $this->_platform->getDoctrineTypeMapping($dbType); return $database['Database']; }
Editing vendor files is never an appropriate answer, regardless of how many "beware" you put after it.
3

I think the easiest way to fix this issue is adding a mapping type to doctrine.yaml if applicable so that enum will be treated as string.

doctrine:
    dbal:
        #other configuration
        mapping_types:
            enum: string

Comments

-1

If you ever run into the error below on a Doctrine with Laminas setup. Find the source of the enum column because my source code contains nothing like it.

Unknown database type enum requested

It was a table schema that phpMyAdmin created in the database that Doctrine wanted to match/sync with my schema definition. And it couldn’t find the enum column contained in the phpMyAdmin schema.

I solved it by moving the pma_ tables to a different database.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.