繁体   English   中英

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

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

假设我有一个在生产环境中运行的代码,因此,我无法更改相同的迁移文件以添加新列,如下所示

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');
    }
}

在第一个版本之后,我想从名为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);
    }
}

并使用vendor/bin/phpunit我运行我的测试

请注意,首先数据库将被迁移,并且由于该测试方法没有开始

SQLite 抛出如下错误。

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')

您不得使用DB::statement和您的sprintf来修改您的字段。

因此,您可以使用 Laravel 迁移机制的内置 function change ,如下所示:

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

请参阅: Laravel 迁移:修改列

我已经搜索并找到了这个解决方案,希望有用。

我的问题是数据库的行为和对键的支持,当您使用 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

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');
}

然后你可以改变你的enum列,如下所示

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

并且知道在测试中更改枚举类型字段没有问题。

注意:此解决方案是doctrine 项目站点上为ENUM类型提供的解决方案之一,它提供了两种解决方案,第一个是Mapping to varchars ,第二个是Defining a custom type for enum

如果上述解决方案对您不起作用,那么您可以在doctrine 项目的站点中阅读有关此问题的更多信息以及如何解决它

暂无
暂无

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

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