Laravel 5.1未知数据库类型枚举请求

时间:2015-10-15 05:52:55

标签: php laravel laravel-4 laravel-5

在运行 php artisan migrate 时,我收到以下错误

  

[学说\ DBAL \ DBALException]
    请求未知的数据库类型枚举,Doctrine \ DBAL \ Platforms \ MySqlPlatform可能不支持它。

如何解决此问题。

代码:

public function up() {
    Schema::table('blogs', function (Blueprint $table) {
        $table->string('wordpress_id')->nullable();
        $table->string('google_blog_id')->nullable()->change();
    });
}

8 个答案:

答案 0 :(得分:62)

这是Laravel 5.1 documentation中所述的已知问题。

  

注意:目前不支持重命名表中包含enum的列。

当数据库表中有nullable列时会发生这种情况。无论您是要重命名其他列,还是将其他列更改为Doctrine\DBAL,都会显示此错误。这是public function __construct() { DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); } 的问题。

轻松修复就是在数据库迁移文件中添加此构造函数方法。

ENUM

这会将所有VARCHAR()列映射到{{1}},该列将接受任何字符串。

  

这对Laravel 5.1和Laravel 5.3起作用。我希望很快就能解决这个问题。

感谢@ Gmatkowski的答案 https://stackoverflow.com/a/32860409/1193201

答案 1 :(得分:57)

官方Laravel 5.1 documentation声明:

  

注意:目前不支持使用枚举列重命名表中的列。

如果您尝试更改其他列,则无关紧要,如果该表包含enum 任何地方,则无效。这是一个Doctrine DBAL问题。

作为一种解决方法,您可以删除该列并添加一个新列(列数据将丢失):

public function up()
{
    Schema::table('users', function(Blueprint $table)
    {
        $table->dropColumn('name');
    });

    Schema::table('users', function(Blueprint $table)
    {
        $table->text('username');
    });
}

或使用DB语句:

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

来源:https://github.com/laravel/framework/issues/1186

答案 2 :(得分:3)

真正的肮脏解决方案,无论如何都能完成工作

update Doctrine/DBAL/Schema/MySqlSchemaManager.php 

将这些线放在第113行上方

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

请注意不建议直接更新供应商文件,因为如果vonder选择更新插件,您的更改可能会被覆盖

答案 3 :(得分:3)

您可以使用以上建议,也可以将以下代码添加到迁移文件中...

JsonView

答案 4 :(得分:2)

我通过创建一个新的迁移类并从该类进行扩展来摆脱了这个问题。也许有多种方法可以使它更“标准”,但这只是一个非常简单的案例,对我们的团队来说是完美的。

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

然后如前所述,只是从中扩展迁移

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

答案 5 :(得分:0)

您完全不应使用枚举。即使使用laravel 5.8,问题也无法解决。

感谢所有提醒我的人

Laravel 5.1 documentation官方声明:

  

注意:当前不支持使用enum列重命名表中的列。

我需要补充的是,在enum列声明中添加可用选项时,您也会遇到同样的问题。

我得出的结论是,您应谨慎使用枚举。甚至您根本不应使用枚举。

我无法投票通过字符串替换枚举的任何答案。否,您需要创建一个查找表,并用unsignedInteger作为foreign key替换枚举。

这是很多工作,如果没有单元测试,您会很烦恼,但这是一个正确的解决方案。

您可能会因为正确执行此操作而被解雇,因为这花费了太长时间,但是,不用担心,您会找到更好的工作。 :)

下面是一个例子,说明如何在enum列声明中添加可用选项

说你有这个:

Schema::create('blogs', function (Blueprint $table) {
    $table->enum('type', [BlogType::KEY_PAYMENTS]);
    $table->index(['type', 'created_at']);
...

并且您需要提供更多类型

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

答案 6 :(得分:0)

我认为解决此问题的最简单方法是在doctrine.yaml中添加一个映射类型(如果适用),以便将枚举视为字符串。

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

答案 7 :(得分:0)

Laravel:5.8

use Doctrine\DBAL\Types\StringType;
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');
    }