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();
});
}
公式のLaravel 5.1 ドキュメント 状態:
注:列挙列を使用したテーブルの列名の変更は現在サポートされていません。
テーブルにenum
anywhereが含まれている場合、別の列を変更しようとしても問題はありません。これは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)');
}
Laravel 5.1 documentation に記載されている既知の問題です。
注:
enum
列を使用したテーブルの列の名前の変更は現在サポートされていません。
データベーステーブルにenum
列がある場合に発生します。別の列の名前を変更しようとしても、別の列をnullable
に変更しようとしても、このバグが表示されます。 _Doctrine\DBAL
_の問題です。
簡単な修正これは、データベースマイグレーションファイルにこのコンストラクターメソッドを追加するだけです。
_public function __construct()
{
DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
}
_
これにより、すべてのENUM
列がVARCHAR()
にマップされ、列は任意の文字列を受け入れます。
これはLaravel 5.1およびLaravel 5.3。このバグがすぐに修正されることを願っています。
@ Gmatkowskiの回答に対するクレジットhttps://stackoverflow.com/a/32860409/1193201
本当に汚い解決策であり、それでも仕事をやり遂げる
update Doctrine/DBAL/Schema/MySqlSchemaManager.php
これらの行を113行のすぐ上に追加します
$this->_platform->registerDoctrineTypeMapping('enum', 'string');
$type = $this->_platform->getDoctrineTypeMapping($dbType);
ベンダーがプラグインの更新を選択した場合、変更が上書きされる可能性があるため、ベンダーファイルを直接更新することはお勧めできません。
新しい移行クラスを作成し、それから移行を拡張することで、この問題を取り除きます。それをもっと「標準」にする方法は複数あるかもしれませんが、これは私たちのチームにとって完璧に機能する非常に単純なケースです。
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');
}
}
enumはまったく使用しないでください。 laravel 5.8でも、問題は解決しません。
それを思い出したみんなに感謝します
公式のLaravel 5.1 ドキュメント 状態:
注:列挙列を使用したテーブルの列名の変更は現在サポートされていません。
利用可能なオプションを追加するがenum
列宣言にある場合、同じ問題が発生することを追加する必要があります。
enumを注意して使用する必要があります。またはenumを使用しないでくださいという結論に至ります。
Enumをstringに置き換えることを提案する回答に投票することはできません。いいえ、ルックアップテーブルを作成し、enumをforeign key
としてunsignedInteger
に置き換える必要があります。
それは多くの作業であり、単体テストのカバレッジなしでそれを行うことに動揺するでしょうが、これは正しい解決策です。
時間がかかりすぎるので、これを正しく行うと解雇されることもありますが、心配しないで、より良い仕事を見つけるでしょう。 :)
これがどれほど難しいかという例です利用可能なオプションを追加する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']);
});
}
この問題を修正する最も簡単な方法は、該当する場合はdoctrine.yamlにマッピングタイプを追加して、enumが文字列として扱われるようにすることだと思います。
doctrine:
dbal:
#other configuration
mapping_types:
enum: string