简体   繁体   English

如何在测试 laravel 中更改迁移中的枚举类型列

[英]how to alter enum type column in migration in testing laravel

assuming that I have a code that is running on production and because of this, I can not alter the same migration file for adding new columns, like bellow假设我有一个在生产环境中运行的代码,因此,我无法更改相同的迁移文件以添加新列,如下所示

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name')->nullable();
            $table->string('email')->unique();
            $table->string('token_key')->unique()->nullable();
            $table->enum('type', ['avatar', 'image', 'video'])->comment(implode(', ', ['avatar', 'image', 'video']));
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

and after the first release, I want to remove avatar value from the column named type acceptable values, So I add a new migration file for adding my new column like below在第一个版本之后,我想从名为type可接受值的列中删除avatar值,所以我添加了一个新的迁移文件来添加我的新列,如下所示

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class ChangeEnumOnUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        $sql = sprintf(
            "ALTER TABLE %s CHANGE `%s` `%s` ENUM('%s') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '%s'",
            'users',
            'type',
            'type',
            implode('\',\'', ['image', 'video']),
            implode(',', ['image', 'video'])
        );
        DB::statement($sql);
    }
}

and using vendor/bin/phpunit i run my test并使用vendor/bin/phpunit我运行我的测试

please attention that first of all database will get migrated and because of that test method does not getting started请注意,首先数据库将被迁移,并且由于该测试方法没有开始

And SQLite is throwing error like below. SQLite 抛出如下错误。

The SQLite exception is like SQLite 异常就像

PDOException: SQLSTATE[HY000]: General error: 1 near "CHANGE": syntax error

Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1 near "CHANGE": syntax error (SQL: ALTER TABLE users CHANGE `type` `type` ENUM('image','video') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'image,video')

You may not use DB::statement and your sprintf to modify your field.您不得使用DB::statement和您的sprintf来修改您的字段。

So you may use the built-in function change of Laravel migration mechanism like that:因此,您可以使用 Laravel 迁移机制的内置 function change ,如下所示:

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->change(); // update the field by increasing the max allowed characters
});

See: Laravel Migration: Modifying Columns请参阅: Laravel 迁移:修改列

I have searched and found this solution, hope to be useful.我已经搜索并找到了这个解决方案,希望有用。

my problem was database's behavior and supporting of keys, when you use laravel's migration functionalities for changing an enum type you must first add doctrine/dbal package to your project我的问题是数据库的行为和对键的支持,当您使用 laravel 的迁移功能来更改enum类型时,您必须首先将doctrine/dbal package 添加到您的项目中

 composer require doctrine/dbal

then you must add enum type to doctrine because laravel is using the package to manipulate tables column and this laravel did not add enum type to the doctrine by default so __construct method in your altering migration is needed like below then you must add enum type to doctrine because laravel is using the package to manipulate tables column and this laravel did not add enum type to the doctrine by default so __construct method in your altering migration is needed like below

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\StringType;

public function __construct()
{
    if (! Type::hasType('enum')) {
        Type::addType('enum', StringType::class);
    }
    DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
}

then you can change your enum column like below然后你可以改变你的enum列,如下所示

$table->enum('type', ['avatar', 'video'])
      ->comment(implode(', ', ['avatar', 'video']))
      ->change();

and know there is no problem on change an enum type field on testing.并且知道在测试中更改枚举类型字段没有问题。

ATTENTION : this solution is one of the offered solutions for ENUM types on doctrine project's site , and it offers two solutions, the first one is Mapping to varchars and the second one is Defining a custom type for enum注意:此解决方案是doctrine 项目站点上为ENUM类型提供的解决方案之一,它提供了两种解决方案,第一个是Mapping to varchars ,第二个是Defining a custom type for enum

If the above solution did not work for you, then you can read more about this issue and how to solve it in doctrine project's site your self如果上述解决方案对您不起作用,那么您可以在doctrine 项目的站点中阅读有关此问题的更多信息以及如何解决它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM