Laravel迁移变为使列可以为空

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Laravel迁移变为使列可以为空相关的知识,希望对你有一定的参考价值。

我使用unsigned user_id创建了一个迁移。如何在新的迁移中编辑user_id以使其成为nullable()

Schema::create('throttle', function(Blueprint $table)
{
    $table->increments('id');
    // this needs to also be nullable, how should the next migration be?
    $table->integer('user_id')->unsigned();
}
答案

Laravel 5现在支持更换列..

来自官方文档的示例

Schema::table('users', function($table)
{
    $table->string('name', 50)->nullable()->change();
});

来源:http://laravel.com/docs/5.0/schema#changing-columns

Laravel 4不支持修改列。你必须编写raw sql命令。

  // getting Laravel App Instance
   $app = app();

  // getting laravel main version
   $laravelVer = explode('.',$app::VERSION);

    switch ($laravelVer[0]) {

        case('5') :                
            Schema::table('pro_categories_langs', function(Blueprint $t) {
                $t->string('name', 100)->nullable()->default(null)->change();
            });               
            break;                
        /**
         * it is not L5 !!
         */
        default :                
             DB::statement('ALTER TABLE `pro_categories_langs` MODIFY `name` VARCHAR(100) NULL;');                                  
    }
另一答案

我假设您正在尝试编辑已添加数据的列,因此在不丢失数据的情况下删除列并再次添加为可为空的列是不可能的。我们将alter现有专栏。

但是,Laravel的架构构建器不支持修改列以外的列。因此,您需要运行原始查询来执行它们,如下所示:

function up()
{
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
}

为了确保您仍然可以回滚迁移,我们也会执行down()

function down()
{
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

需要注意的是,由于您要在可空和可空之间进行转换,因此您需要确保在迁移之前/之后清理数据。所以在迁移脚本中以这两种方式执行此操作:

function up()
{
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
    DB::statement('UPDATE `throttle` SET `user_id` = NULL WHERE `user_id` = 0;');
}

function down()
{
    DB::statement('UPDATE `throttle` SET `user_id` = 0 WHERE `user_id` IS NULL;');
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}
另一答案

以下是未来读者的完整答案。请注意,这仅适用于Laravel 5+。

首先,你需要学说/ dbal包:

composer require doctrine/dbal

现在,在迁移中,您可以执行此操作以使列可为空:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        // change() tells the Schema builder that we are altering a table
        $table->integer('user_id')->unsigned()->nullable()->change();
    });
}

您可能想知道如何还原此操作。遗憾的是,不支持此语法:

// Sadly does not work :'(
$table->integer('user_id')->unsigned()->change();

这是还原迁移的正确语法:

$table->integer('user_id')->unsigned()->nullable(false)->change();

或者,如果您愿意,可以编写原始查询:

public function down()
{
    /* Make user_id un-nullable */
    DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
    DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

希望你会发现这个答案很有用。 :)

另一答案

他是Laravel 5的全面迁移:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->unsignedInteger('user_id')->nullable()->change();
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->unsignedInteger('user_id')->nullable(false)->change();
    });
}

关键是,你可以通过传递nullable作为参数来删除false

另一答案

如果您碰巧更改了列并偶然发现了

'DoctrineDBALDriverPDOmysqlDriver' not found

然后只需安装

composer require doctrine/dbal

另一答案

添加到Dmitri Chebotarev答案,

如果要一次更改多个列,可以执行以下操作

DB::statement('
     ALTER TABLE `events` 
            MODIFY `event_date` DATE NOT NULL,
            MODIFY `event_start_time` TIME NOT NULL,
            MODIFY `event_end_time` TIME NOT NULL;
');
另一答案

加入Dmitri Chebotarev的答案,就像Laravel 5+一样。

在要求学说/ dbal包之后:

composer require doctrine/dbal

然后,您可以使用可空列进行迁移,如下所示:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        // change() tells the Schema builder that we are altering a table
        $table->integer('user_id')->unsigned()->nullable()->change();
    });
}

要恢复操作,请执行以下操作:

public function down()
{
    /* turn off foreign key checks for a moment */
    DB::statement('SET FOREIGN_KEY_CHECKS = 0');
    /* set null values to 0 first */
    DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
    /* alter table */
    DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
    /* finally turn foreign key checks back on */
    DB::statement('SET FOREIGN_KEY_CHECKS = 1');

}

另一答案

试试吧:

$table->integer('user_id')->unsigned()->nullable();
另一答案

对于Laravel 4.2,Unnawut上面的回答是最好的。但是如果你使用表前缀,那么你需要稍微改变你的代码。

function up()
{
    $table_prefix = DB::getTablePrefix();
    DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
}

为了确保您仍然可以回滚迁移,我们也会执行down()

function down()
{
    $table_prefix = DB::getTablePrefix();
    DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

以上是关于Laravel迁移变为使列可以为空的主要内容,如果未能解决你的问题,请参考以下文章

在 Laravel 5 迁移中使列不可为空

如何在 Ruby on Rails 迁移中使列唯一并为其编制索引?

在 laravel 中更改迁移值

如果请求值为空,Laravel 设置默认值

Laravel 8:检查数据库中的记录是不是为空

需要一种有效的方法来避免使用 Laravel 5 重复代码片段