如何使用 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 模式构建器更改列类型?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 模式构建器主键作为外键

Laravel - 使用 Eloquent 查询构建器在选择中添加自定义列

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

使用 laravel 构建器的 JSON 列查询

雄辩的查询构建器laravel 5.6中的未知列

Laravel,如何将集合对象转换为构建器对象