Laravel 5.1 Запрошен неизвестный тип базы данных
Во время запуска 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();
});
}
10 ответов
Официальная документация Laravel 5.1 гласит:
Примечание. Переименование столбцов в таблице со столбцом перечисления в настоящее время не поддерживается.
Неважно, если вы пытаетесь изменить другой столбец, если таблица содержит enum
нигде не получится. Это проблема доктрины DBAL.
В качестве обходного пути вы можете либо удалить столбец, либо добавить новый (данные столбца будут потеряны):
public function up()
{
Schema::table('users', function(Blueprint $table)
{
$table->dropColumn('name');
});
Schema::table('users', function(Blueprint $table)
{
$table->text('username');
});
}
или используйте оператор БД:
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.
Примечание. Переименование столбцов в таблице с помощью
enum
столбец в настоящее время не поддерживается.
Это происходит, когда у вас есть enum
столбец в вашей таблице базы данных. Пытаетесь ли вы переименовать другой столбец или изменить другой столбец на nullable
эта ошибка появится. Это проблема сDoctrine\DBAL
,
Этолегко исправить, просто добавив этот метод конструктора в файл миграции базы данных.
public function __construct()
{
DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
}
Это отобразит всеENUM
столбцы вVARCHAR()
и столбец примет любую строку.
Это работало для меня на Laravel 5.1 и Laravel 5.3. Я надеюсь, что эта ошибка может быть исправлена в ближайшее время.
Благодарим @Gmatkowski за ответ на /questions/8036677/migratsiya-bazyi-dannyih-laravel-oshibka-renamecolumn-zaprashivaetsya-perechislenie-neizvestnogo-tipa-bazyi-dannyih/8036698#8036698
Я избавился от этой проблемы, создав новый класс миграции и расширив возможности миграции. Есть несколько способов сделать больше "стандартными", но это очень простой случай, который идеально подходит для меня.
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 {
DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
Type::addType('enum', StringType::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');
}
}
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');
}
Вы не должны использовать enum вообще. Даже с laravel 5.8 проблема не решена.
Спасибо всем, кто напомнил, что
Официальная документация Laravel 5.1 гласит:
Примечание. Переименование столбцов в таблице со столбцом перечисления в настоящее время не поддерживается.
Мне нужно добавить, что у вас будет такая же проблема при добавлении доступных опций в enum
объявление столбца.
Это приводит меня к выводу, что Вы должны использовать enum с осторожностью. или даже вы не должны использовать enum вообще.
Я не могу проголосовать ни за какой ответ, предлагающий заменить enum на string. НЕТ, вам нужно создать таблицу поиска и заменить 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']);
});
}
У меня была такая же проблема, я мог решить ее в Laravel10.x
следующими способами:
Вариант 1. Использование собственных операций схемы.
Вы должны позвонитьSchema::useNativeSchemaOperationsIfPossible()
метод в методе загрузки вашегоApp\Providers\AppServiceProvider
class или в файлах миграции, чтобы иметь возможность использовать собственные операции схемы.
Использованная литература:
Вариант 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');
}
Вариант 3. Использование операторов БД
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';");
}
Ссылка
Действительно грязное решение, которое выполняет работу, тем не менее, было бы
update Doctrine/DBAL/Schema/MySqlSchemaManager.php
добавив эти строки чуть выше линии 113
$this->_platform->registerDoctrineTypeMapping('enum', 'string');
$type = $this->_platform->getDoctrineTypeMapping($dbType);
Помните, что обновление файлов вендора напрямую не рекомендуется, потому что в случае, если vonder решит обновить плагин, ваши изменения могут быть перезаписаны
Вы можете использовать приведенные выше предложения или добавить приведенный ниже код в свой файл миграции...
public function up()
{
DB::connection()->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
Schema::table('<YOUR_TABLE>', function (Blueprint $table) {
//YOUR CHANGES HERE
}
}
Я думаю, что самый простой способ решить эту проблему - добавить тип сопоставления в doctrine.yaml, если это применимо, чтобы enum обрабатывался как строка.
doctrine:
dbal:
#other configuration
mapping_types:
enum: string
Если вы когда-нибудь столкнетесь с приведенной ниже ошибкой при настройке Doctrine с Laminas. Найдите источник столбца перечисления, потому что мой исходный код не содержит ничего подобного.
Запрошено перечисление неизвестного типа базы данных
Это была схема таблицы, созданная phpMyAdmin в базе данных, которую Doctrine хотела сопоставить/синхронизировать с моим определением схемы. И он не смог найти столбец перечисления, содержащийся в схеме phpMyAdmin.
Я решил это, переместив
pma_
таблицы в другую базу данных.