Изменение миграции Laravel, чтобы сделать столбец допускающим значение NULL

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

person user391986    schedule 25.06.2014    source источник


Ответы (9)


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]) {

    // Laravel 4
    case('4'):

        DB::statement('ALTER TABLE `pro_categories_langs` MODIFY `name` VARCHAR(100) NULL;');
        break;

    // Laravel 5, or Laravel 6
    default:                

        Schema::table('pro_categories_langs', function(Blueprint $t) {
            $t->string('name', 100)->nullable()->change();
        });               

}
person MURATSPLAT    schedule 08.03.2015
comment
Спасибо за это. Но как я могу сделать обратное? Как изменить столбец, чтобы он не допускал значения NULL? Любые идеи? - person algorhythm; 28.04.2015
comment
@algorhythm Вы попробуете эту '$ t- ›string (' name ', 100) -› change ();' - person MURATSPLAT; 01.05.2015
comment
@MURATSPLAT Нет, я сделал это с DB::statement и сырым SQL ... Но, может быть, я попробую позже ... Спасибо - person algorhythm; 01.05.2015
comment
Вам необходимо потребовать doctrine \ dbal для миграции - person younes0; 16.12.2015
comment
@algorhythm ->nullable(false) позволит вам снова изменить столбец. - person Colin; 10.02.2016
comment
- ›change () требует, чтобы вы установили пакет Doctrine DBAL, и он по своей сути не распознает все те же типы столбцов, которые доступны из коробки из laravel .. например, double не является распознанным типом столбца для DBAL. - person Will Vincent; 09.05.2016
comment
Это не сработает, если вы попытаетесь переименовать столбец в одной и той же функции, вам нужно запустить 2 функции в одной таблице для выполнения переименования и изменения. - person Yevgeniy Afanasyev; 16.03.2017
comment
@MURATSPLAT: у меня такая же проблема, и пока я добавляю зависимость doctrine / dbal в свой файл composer.json, метод change не распознается и не работает. Я устанавливаю Laravel 5.7. - person maryam; 13.10.2018
comment
@MURATSPLAT. Привет. Моя проблема решена. Я должен записать отредактированный столбец в новый файл миграции и перенести его, но я перенесу предыдущий файл миграции. - person maryam; 15.10.2018

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

Прежде всего вам понадобится пакет doctrine / dbal:

composer require doctrine/dbal

Теперь в процессе миграции вы можете сделать это, чтобы сделать столбец допускающим значение NULL:

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

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

person Dmitri Chebotarev    schedule 14.09.2015
comment
Это наиболее полный ответ для L5, но следует отметить, что если user_id является внешним ключом, каким он должен быть, вы не сможете его изменить, если не запустите DB :: statement ('SET FOREIGN_KEY_CHECKS = 0 ');' первый. И установите его обратно на 1, когда закончите. - person rzb; 15.01.2016
comment
Спасибо, nullable(false) спас меня от выдергивания волос, потому что nullable() плохо документирован, и нет notNull() функции. - person Zack Morris; 01.12.2016
comment
это не работает для внешних ключей с postgres. попытка SET FOREIGN_KEY_CHECKS = 0 дает ошибку. вам, вероятно, потребуется изменить ограничения таблицы с помощью необработанного запроса. см. здесь: postgresql.org/docs/current/static/sql-altertable .html - person szaman; 07.06.2017
comment
Это ломает мои тесты. Тесты запускаются и зависают. Полагаю, причиной этого является первый откат. Вызывает зависание тестов как для MySQL, так и для SQLite. - person Thomas Praxl; 19.07.2018

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

Одно замечание заключается в том, что, поскольку вы выполняете преобразование между допускающими значение NULL и не допускающими значения 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;');
}
person Unnawut    schedule 26.06.2014
comment
Для Laravel 4 замените query на statement - person Razor; 27.06.2014
comment
Спасибо @Razor. Соответственно обновил свой ответ. - person Unnawut; 06.10.2014
comment
В функции down во втором блоке кода оператор SQL должен заканчиваться на NOT NULL. (Функция down в третьем примере верна.) - person Scott Weldon; 03.09.2015

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

person Yauheni Prakopchyk    schedule 04.02.2016

Если случайно поменял столбцы и наткнулся на

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

тогда просто установите

composer require doctrine/dbal

person ken    schedule 07.07.2015
comment
Это укусило меня, поэтому я пошел дальше и упростил отслеживание исключения / решения: github.com/laravel / framework / pull / 10002 - person Beau Simensen; 21.08.2015

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

После запроса пакета doctrine / dbal:

composer require doctrine/dbal

Затем вы можете выполнить миграцию с столбцами, допускающими значение NULL, например:

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');
}
person rzb    schedule 19.01.2016

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

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

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;
');
person Sameer    schedule 07.11.2015

Попытайся:

$table->integer('user_id')->unsigned()->nullable();
person Adil    schedule 26.06.2014
comment
Это не меняет существующий столбец - person dVaffection; 22.01.2015
comment
вы забыли ->change в конце и упомянули только Laravel 5+ - person Alexander Malakhov; 15.07.2015
comment
Вам необходимо потребовать composer require doctrine/dbal - person Lizesh Shakya; 16.12.2019

Для 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;');
}
person Debiprasad    schedule 09.03.2018