Laravel Migration - 更新枚举选项

时间:2014-08-11 19:47:56

标签: laravel

我尝试使用架构构建器向表中添加枚举选项(不丢失当前数据集)。

我唯一能够找到关于列更改的唯一内容是http://www.flipflops.org/2013/05/25/modify-an-existing-database-column-in-a-laravel-migration/,我相信这是为Laravel3编写的。

即便如此,我尝试使用DB :: query(' ALTER TABLE ...');命令,但它出错了call_user_func_array()期望参数1是一个有效的回调,类' Illuminate \ Database \ MySqlConnection'没有方法'查询'。

DB::query("ALTER TABLE users CHANGE COLUMN permissions permissions ENUM('admin', 'user', 'candidate')");

我也试过这样做:

Schema::table('users', function ($table) {
    $table->enum('permissions', array('admin', 'user', 'candidate'))->default('user');
});

但是错误地说该列已经存在。

在不丢失该列中的所有数据的情况下,做我想做的事情的最佳方法是什么?

3 个答案:

答案 0 :(得分:75)

使用DB::statement方法:

DB::statement("ALTER TABLE users CHANGE COLUMN permissions permissions ENUM('admin', 'user', 'candidate') NOT NULL DEFAULT 'user'");

答案 1 :(得分:3)

我已将 Joseph's answer 改编为一种方法,您可以将其添加到迁移中,然后使用一组值进行调用,而不是将它们硬编码在语句中。它对带引号的值没有任何花哨的处理,所以请只使用合理的值,或者自己修改。

private function setEnumValues($table, $column, array $values, $nullable = false, $default = null)
{
    $quotedValues = collect($values)
        ->map(function ($value) {
            return "'${value}'";
        })
        ->join(', ');

    $suffix = '';

    if (!$nullable) {
        $suffix .= ' NOT NULL';
    }

    if ($default) {
        $suffix .= " DEFAULT '${default}'";
    }

    $statement = <<<SQL
ALTER TABLE ${table} CHANGE COLUMN ${column} ${column} ENUM(${quotedValues}) ${suffix}
SQL;

    \Illuminate\Support\Facades\DB::statement($statement);
}

您可能会像这样在迁移中使用它:

<?php

use Illuminate\Database\Migrations\Migration;

class AddQueuedStatusToPaymentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // Add the new 'queued' value

        $this->setEnumValues(
            'payments',
            'status',
            [
                'queued',
                'processing',
                'successful',
                'failed',
            ],
            false, // Not nullable
            'queued' // Mark it as the default for all new payments
        );
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        // Remove the new 'queued' value
        
        $this->setEnumValues(
            'payments',
            'status',
            [
                'processing',
                'successful',
                'failed',
            ],
            false, // Not nullable
            'processing' // Set the default back to processing for all new payments
        );
    }

    private function setEnumValues($table, $column, array $values, $nullable = false, $default = null)
    {
        $quotedValues = collect($values)
            ->map(function ($value) {
                return "'${value}'";
            })
            ->join(', ');

        $suffix = '';

        if (!$nullable) {
            $suffix .= ' NOT NULL';
        }

        if ($default) {
            $suffix .= " DEFAULT '${default}'";
        }

        $statement = <<<SQL
ALTER TABLE ${table} CHANGE COLUMN ${column} ${column} ENUM(${quotedValues}) ${suffix}
SQL;

        \Illuminate\Support\Facades\DB::statement($statement);
    }
}

答案 2 :(得分:0)

修改列

先决条件

在修改列之前,请确保将doctrine / dbal依赖项添加到您的composer.json文件中。 Doctrine DBAL库用于确定列的当前状态,并创建对列进行指定调整所需的SQL查询:

Schema::table('users', function (Blueprint $table) { 
    $table->enum('name', [])->change(); 
});

https://laravel.com/docs/5.8/migrations#modifying-columns