Laravel 5.1 Неизвестное имя типа базы данных

Во время миграции php artisan я получил следующую ошибку

[Учение\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();
    });
}

Ответы

Ответ 1

Официальная документация Laravel 5.1 гласит:

Примечание. Переименование столбцов в таблице с столбцом перечисления в настоящее время не поддерживается.

Не имеет значения, пытаетесь ли вы изменить другой столбец, если таблица содержит enum любом месте, где оно не будет работать. Это проблема DBAL Doctrine.

В качестве обходного пути вы можете либо удалить столбец, либо добавить новый (данные столбца будут потеряны):

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

Это известный вопрос, как указано в документации 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 на fooobar.com/questions/356238/...

Ответ 3

Реальное грязное решение, которое выполняет свою работу, тем не менее будет

update Doctrine/DBAL/Schema/MySqlSchemaManager.php 

добавив эти строки чуть выше строки 113

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

Помните, что обновление файлов поставщика напрямую нецелесообразно, поскольку в случае, когда vonder выбирает обновление плагина, ваши изменения могут быть перезаписаны

Ответ 4

Я избавился от этой проблемы, создав новый класс миграции и расширив возможности миграции. Может быть, есть несколько способов сделать его более "стандартным", но это очень простой случай, который идеально подходит для нашей команды.

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

Вы не должны использовать 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']);
    });
}

Ответ 6

Я думаю, что самый простой способ решить эту проблему - это добавить тип отображения в doctrine.yaml, если это применимо, так что enum будет рассматриваться как строка.

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