如何在测试中更改迁移中的枚举类型列 laravel
how to alter enum type column in migration in testing laravel
假设我有一个在生产环境中 运行ning 的代码,因此,我无法更改相同的迁移文件来添加新列,如下所示
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
我 运行 我的测试
please attention that first of all database will get migrated and because of that test method does not getting started
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迁移机制的内置函数change
:
Schema::table('users', function (Blueprint $table) {
$table->string('name', 50)->change(); // update the field by increasing the max allowed characters
});
我已经搜索并找到了这个解决方案,希望有用。
我的问题是数据库的行为和键的支持,当您使用 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 site 自己
中阅读有关此问题以及如何解决它 ]
假设我有一个在生产环境中 运行ning 的代码,因此,我无法更改相同的迁移文件来添加新列,如下所示
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
我 运行 我的测试
please attention that first of all database will get migrated and because of that test method does not getting started
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迁移机制的内置函数change
:
Schema::table('users', function (Blueprint $table) {
$table->string('name', 50)->change(); // update the field by increasing the max allowed characters
});
我已经搜索并找到了这个解决方案,希望有用。
我的问题是数据库的行为和键的支持,当您使用 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 site 自己
中阅读有关此问题以及如何解决它 ]