如何使用 Laravel 模式构建器更改列类型?
Posted
技术标签:
【中文标题】如何使用 Laravel 模式构建器更改列类型?【英文标题】:How do I change a column type with Laravel schema builder? 【发布时间】:2014-03-30 09:40:38 【问题描述】:我需要将两个字段从整数更改为外键。我如何构建我的迁移来做到这一点?
Schema::create('messages', function($table)
$table->increments('id');
$table->integer('sender');
$table->integer('recipient');
$table->string('title');
$table->longtext('body');
$table->timestamps();
$table->softDeletes();
$table->integer('regarding');
);
我会将sender
更改为sender_id
,将recipient
更改为recipient_id
,将regarding
更改为regarding_id
。
【问题讨论】:
【参考方案1】:您可以使用 change() 函数更改列名。这里我提到了一个模式表作为示例
Schema::table('person', function (Blueprint $table)
$table->increments('id');
$table->text('name')->nullable()->change();
$table->integer('number')->nullable()->change();
$table->integer('billing_day')->nullable()->change();
$table->timestamps()->nullable()->change();
);
【讨论】:
【参考方案2】:在 Laravel 5 中,您可以使用如下所示的闭包。这应该以与数据库无关的方式进行,因此无需使用 if 语句检查数据库类型。
(请注意,您可能需要 composer 要求教义/dbal 来执行此操作。)
public function up()
Schema::table('plans', function($t)
$t->renameColumn('duration_change_type', 'duration');
);
public function down()
Schema::table('plans', function($t)
$t->renameColumn('duration', 'duration_change_type');
);
【讨论】:
【参考方案3】:我会删除它,然后将其重新添加为不同的类型。
【讨论】:
【参考方案4】:如果要更改列类型或修改长度等,只需调用change()
方法
Schema::table('users', function ($table)
$table->string('id')->change();
);
并重命名列
Schema::table('users', function ($table)
$table->renameColumn('from', 'to');
);
【讨论】:
@JoanPicornell 乐于提供帮助 :) 有效。只要确保你首先运行composer require doctrine/dbal
,按照Laravel docs
卡在将类型字符串更改为整数
@AminShojaei 你是在链尾调用 change 方法吗?【参考方案5】:
别想太多,我用的是下面的代码。这里我把数据类型从varchar改成text。
public function up()
DB::statement('ALTER TABLE items MODIFY COLUMN item_description TEXT');
DB::statement('ALTER TABLE items MODIFY COLUMN delivery_description TEXT');
public function down()
DB::statement('ALTER TABLE items MODIFY COLUMN item_description VARCHAR(255)');
DB::statement('ALTER TABLE items MODIFY COLUMN delivery_description VARCHAR(255)');
【讨论】:
这不适用于 Postgres,您必须使用它: DB::statement('ALTER TABLE items ALTER COLUMN item_description TYPE VARCHAR(20)'); 这是最好的答案。达到 ORM 所能达到的极限是很常见的。您需要知道原始查询何时是更好的选择。 不确定它当时是否不存在,但现在这是非常糟糕的做法。应该使用 Chaudhry Waqas 回答中看到的 ->change() 方法。【参考方案6】:我刚刚遇到同样的问题,最快的解决方案是简单地更改数据库上的列结构,然后更改原始迁移以反映对数据库所做的更改。
这样,如果迁移被回滚然后再次向上,则将创建正确的字段。只要您确保准确地更改迁移,我看不出有任何不利之处。
【讨论】:
如果只部署到一台服务器也可以,但是如果部署到10台服务器,你会去每台单独更改列吗? 不好的做法。你正在失去迁移的目的。考虑一下其他开发人员,他们的本地数据库,他们不知道更改,您现在必须询问他们每个人。【参考方案7】:我遇到了一个类似的问题,需要将列类型从字符串更改为整数。我使用两个单独的迁移(每个迁移都有一个 RAW sql 语句)来解决这个问题。
此外,这适用于 Postgres 和 mysql,因为我们正处于传输过程中。
第一次迁移:
/**
* Run the migrations.
*
* @return void
*/
public function up()
Schema::table('plans', function(Blueprint $table)
//
$table->mediumInteger('duration_change_type')->default(0)->after('duration');
);
if (Config::get('database')['default'] === 'mysql')
// Mysql
DB::statement('update plans set duration_change_type=duration');
else if (Config::get('database')['default'] === 'pgsql')
// PostgreSQL
DB::statement('update plans set duration_change_type=duration::integer');
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
Schema::table('plans', function(Blueprint $table)
//
$table->dropColumn('duration_change_type');
);
第二次迁移:
/**
* Run the migrations.
*
* @return void
*/
public function up()
Schema::table('plans', function(Blueprint $table)
//
$table->dropColumn('duration');
$table->renameColumn('duration_change_type', 'duration');
);
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
Schema::table('plans', function(Blueprint $table)
// Rollback to string
$table->string('duration_change_type')->default(0)->after('duration');
);
if (Config::get('database')['default'] === 'mysql')
// Mysql
DB::statement('update plans set duration_change_type=duration');
else if (Config::get('database')['default'] === 'pgsql')
// PostgreSQL
DB::statement('update plans set duration_change_type=duration::text');
现在考虑一下,可以将其简化为一次迁移。
【讨论】:
【参考方案8】:您可以尝试使用$table->renameColumn('from', 'to');
将列重命名为临时名称,然后使用外键的标准创建行创建新列,最后使用控制器功能将数据从临时列复制到新列。
应该可以,但我没试过,没必要。
【讨论】:
以上是关于如何使用 Laravel 模式构建器更改列类型?的主要内容,如果未能解决你的问题,请参考以下文章