如何在测试 laravel 中更改迁移中的枚举类型列
Posted
技术标签:
【中文标题】如何在测试 laravel 中更改迁移中的枚举类型列【英文标题】:how to alter enum type column in migration in testing laravel 【发布时间】:2020-11-22 08:42:26 【问题描述】:假设我有一个在生产环境中运行的代码,因此,我无法更改相同的迁移文件以添加新列,如下所示
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')
【问题讨论】:
您好,欢迎来到 SO。如果没有详细信息,这将是一个很难解决的问题。添加第二次迁移的内容将是一个很好的输入。你有什么尝试让它发挥作用。 【参考方案1】:您不得使用DB::statement
和sprintf
修改您的字段。
所以你可以像这样使用 Laravel 迁移机制的内置函数change
:
Schema::table('users', function (Blueprint $table)
$table->string('name', 50)->change(); // update the field by increasing the max allowed characters
);
请参阅:Laravel Migration: Modifying Columns
【讨论】:
【参考方案2】:我已经搜索并找到了这个解决方案,希望有用。
我的问题是数据库的行为和对键的支持,当您使用 laravel 的迁移功能来更改 enum
类型时,您必须首先将 doctrine/dbal
包添加到您的项目中
composer require doctrine/dbal
那么您必须将enum
类型添加到学说中,因为 laravel 正在使用该包来操作表列,并且此 laravel 默认情况下没有将enum
类型添加到学说中,因此您需要更改迁移中的 __construct 方法,如下所示
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 project's site 上的ENUM
类型提供的解决方案之一,它提供两种解决方案,第一个是Mapping to varchars
,第二个是Defining a custom type for enum
如果上述解决方案对您不起作用,那么您可以在doctrine project's siteyourself 中阅读有关此问题以及如何解决它的更多信息
【讨论】:
这不起作用 - 迁移将成功运行,但您的列(根据我的经验)从枚举转换为 varchar。这不是预期的行为 @sudoyum 感谢您的评论,我确实添加了学说项目的站点以获得更多解决方案,该站点清楚地说明了问题和解决方案,我希望这个解决方案对您有用以上是关于如何在测试 laravel 中更改迁移中的枚举类型列的主要内容,如果未能解决你的问题,请参考以下文章