Изменение миграции Laravel, чтобы сделать столбец обнуляемым

128

Я создал миграцию с неподписанным 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();
}
Теги:
eloquent
laravel-4
nullable
laravel-migrations

9 ответов

182

Laravel 5 теперь поддерживает изменение столбца.

Пример из официального документа

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

источник: http://laravel.com/docs/5.0/schema#changing-columns

Laravel 4 не поддерживает изменение столбца. Вы должны написать сырую команду 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;');                                  
    }
  • 3
    Спасибо за это. Но как я могу сделать обратное? Как изменить столбец, чтобы он не обнулялся? Есть идеи?
  • 0
    @algorhythm Вы пробуете эту '$ t-> string (' name ', 100) -> change ();'
Показать ещё 8 комментариев
139

Я предполагаю, что вы пытаетесь редактировать столбец, на который уже были добавлены данные, поэтому отбрасывание столбца и добавление снова как столбца с нулевым значением невозможно без потери данных. Мы будем 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;');
}

Одно замечание состоит в том, что, поскольку вы конвертируете между обнуляемыми и не обнуляемыми, вам нужно убедиться, что вы очищаете данные до/после миграции. Так сделайте это в своей миграции script в обоих направлениях:

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;');
}
  • 7
    Для Laravel 4 замените query statement
  • 3
    это должно быть помечено как правильный ответ.
Показать ещё 2 комментария
119

Вот полный ответ для будущего читателя. Обратите внимание, что это возможно только в Laravel 5 +.

Прежде всего вам понадобится пакет doctrine/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;');
}

Надеюсь, вы найдете этот ответ полезным.:)

  • 2
    Это наиболее полный ответ для L5, но следует отметить, что если 'user_id' является внешним ключом, каким он и должен быть, вы не сможете изменить его, если не выполните команду DB :: Statement ('SET FOREIGN_KEY_CHECKS = 0 ');' первый. И установите его обратно в 1, когда вы закончите.
  • 1
    Спасибо, nullable(false) спас меня от выдергивания волос, потому что nullable() плохо документирован, и нет функции notNull() .
Показать ещё 2 комментария
34

Это полная миграция для 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 в качестве аргумента.

13

Если вы столкнулись с изменением столбцов и наткнулись на

'Doctrine\DBAL\Driver\PDOMySql\Driver' not found

затем просто установите

composer require doctrine/dbal

  • 1
    Это меня немного поразило, поэтому я решил сделать исключение / решение проще: github.com/laravel/framework/pull/10002
3

Добавляя к Дмитрию Чеботареву ответ, как для Laravel 5 +.

После запроса пакета doctrine/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');

}

3

Добавление к Дмитрию Чеботареву Ответ,

Если вы хотите изменить несколько столбцов за раз, вы можете сделать это, как показано ниже

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;
');
1

Для 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;');
}
1

Попробуйте:

$table->integer('user_id')->unsigned()->nullable();
  • 1
    Это не изменяет существующий столбец
  • 8
    Вы забыли ->change в конце и упомянуть только Laravel 5+

Ещё вопросы

Сообщество Overcoder
Наверх
Меню