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/
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
我通过创建一个新的迁移类并使我的迁移从它扩展来摆脱这个问题。也许有多种方法可以使其更加“标准”,但这只是一个非常简单的案例,非常适合我们的团队。
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)
拉拉维尔: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)
我遇到了同样的问题,我可以10.x通过以下方式在 Laravel 中解决它:
您必须Schema::useNativeSchemaOperationsIfPossible()在类的引导方法App\Providers\AppServiceProvider或迁移文件中调用方法才能使用本机架构操作。
参考:
在数据库迁移文件中添加此构造函数方法。
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)
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)
参考
你根本不应该使用枚举。即使使用 laravel 5.8,问题也没有解决。
感谢所有提醒这一点的人
Laravel 5.1 官方文档指出:
注意:当前不支持使用枚举列重命名表中的列。
另外,在将可用选项添加到enum列声明中时,您会遇到同样的问题。
它使我得出一个结论,您应该谨慎使用 enum。甚至你根本不应该使用枚举。
我不能投票赞成任何提供用字符串替换枚举的答案。不,您需要创建一个查找表并将 enum 替换unsignedInteger为foreign 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)