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

kar*_*ick 47 php laravel laravel-4 laravel-5

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

[Doctrine\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();
    });
}
Run Code Online (Sandbox Code Playgroud)

小智 83

这是Laravel 5.1 文档中所述的已知问题.

注意:目前不支持使用enum重命名表中的.

当您enum在数据库表中有一列时会发生这种情况.无论您是要重命名另一列,还是更改另一列nullable,都会出现此错误.这是一个问题Doctrine\DBAL.

一个简单的解决方法是在数据库迁移文件中添加此构造函数方法.

public function __construct()
{
    DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
}
Run Code Online (Sandbox Code Playgroud)

这会将所有ENUM列映射到VARCHAR(),列将接受任何字符串.

这对Laravel 5.1和Laravel 5.3起作用.我希望很快就可以修复这个bug.

感谢@ Gmatkowski的回答 /sf/answers/2300228661/

  • 这应该是公认的答案!谢谢@Xeleon (13认同)
  • 这会改变全局类型映射,还是只改变它指定的迁移?如果是全球性的,这会产生任何其他副作用吗?为了确保我使用旧的Laravel 4方式,这也有效(http://laraveldaily.com/schema-builder-changing-table-columns-only-laravel-5-0/). (5认同)
  • 我必须将该行添加到`AppServiceProvider :: boot()`才能使其正常工作. (3认同)

Adr*_*xus 77

Laravel 5.1官方文档指出:

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

如果您尝试更改另一列,则无关紧要,如果该表包含enum 任何无效的列.这是一个Doctrine DBAL问题.

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

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

    Schema::table('users', function(Blueprint $table)
    {
        $table->text('username');
    });
}
Run Code Online (Sandbox Code Playgroud)

或使用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)');
}
Run Code Online (Sandbox Code Playgroud)

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

  • 如果你不使用`$ table`,你不需要在`DB :: statement`周围使用`Schema`换行 (3认同)
  • 感谢您的解决方案,并不总是可以删除列,因此应该手动更改 (2认同)
  • “ doctrine / dbal”到底有什么问题呢,它们不能允许您执行SQL查询中很容易完成的事情? (2认同)

Hec*_*uel 9

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

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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后正如之前所解释的,只需从中扩展您的迁移

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');
    }
}
Run Code Online (Sandbox Code Playgroud)


Wil*_*tes 7

拉拉维尔: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');
    }
Run Code Online (Sandbox Code Playgroud)


ana*_*ojo 6

我遇到了同样的问题,我可以10.x通过以下方式在 Laravel 中解决它:

选项 1:使用本机架构操作

您必须Schema::useNativeSchemaOperationsIfPossible()在类的引导方法App\Providers\AppServiceProvider或迁移文件中调用方法才能使用本机架构操作。

参考:

选项 2:添加学说类型映射

在数据库迁移文件中添加此构造函数方法。

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');
}
Run Code Online (Sandbox Code Playgroud)

选项 3:使用 DB 语句

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';");
}
Run Code Online (Sandbox Code Playgroud)

参考


Yev*_*yev 5

你根本不应该使用枚举。即使使用 laravel 5.8,问题也没有解决。

感谢所有提醒这一点的人

Laravel 5.1 官方文档指出:

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

另外,在将可用选项添加enum列声明中时,您会遇到同样的问题。

它使我得出一个结论,您应该谨慎使用 enum。甚至你根本不应该使用枚举。

我不能投票赞成任何提供用字符串替换枚举的答案。不,您需要创建一个查找表并将 enum 替换unsignedIntegerforeign key.

这是很多工作,如果没有以前的单元测试覆盖,你会很不高兴,但这是一个正确的解决方案。

你甚至可能因为正确地做这件事而被解雇,因为它花费的时间太长,但别担心,你会找到一份更好的工作。:)

这是将可用选项添加enum列声明中的难度示例

说你有这个:

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

并且您需要提供更多类型

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']);
    });
}
Run Code Online (Sandbox Code Playgroud)


小智 5

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

public function up()
    {
DB::connection()->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');

Schema::table('<YOUR_TABLE>', function (Blueprint $table) {
//YOUR CHANGES HERE
}    
    }
Run Code Online (Sandbox Code Playgroud)