列をNULL可能にするためのLaravel移行の変更


194

署名なしの移行を作成しましたuser_iduser_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();
}

回答:


262

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

}

3
このためのTHX。しかし、どうすれば反対のことができますか?列をnullにできないように変更するにはどうすればよいですか?何か案は?
アルゴリズム2015

@algorhythmこれを試してみますか '$ t-> string(' name '、100)-> change();'
MURATSPLAT、2015年

7
移行するにはdoctrine \ dbalが必要です
younes0

33
@algorhythmを使用->nullable(false)すると、列を再び変更できます。
コリン

9
-> change()はDoctrine DBALパッケージをインストールする必要があり、本質的にlaravelから利用できるすべての同じ列タイプを本質的に認識しません。たとえば、doubleはDBALに認識される列タイプではありません。
ヴィンセント

174

これが将来の読者のための完全な答えです。これは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;');
}

この回答がお役に立てば幸いです。:)


3
これはL5の最も完全な回答ですが、「user_id」が外部キーである場合、それが「外部キー」である場合、「DB :: statement( 'SET FOREIGN_KEY_CHECKS」を実行しない限り、それを変更することはできません。 = 0 ');' 最初。完了したら、1に戻します。
rzb

1
文書化されておらず、機能がないnullable(false)ため、髪を抜く手間を省いてくれてありがとう。nullable()notNull()
Zack Morris

これはpostgresの外部キーでは機能しません。試行SET FOREIGN_KEY_CHECKS = 0するとエラーが発生します。生のクエリを使用して、テーブルの制約を変更する必要がある可能性があります。ここを参照してください:postgresql.org/docs/current/static/sql-altertable.html
rrrafalsz

これは私のテストを壊しています。テストの実行が開始され、その後ハングします。最初のロールバックが原因だと思います。MySQLとSQLiteのテストをハングさせます。
Thomas Praxl

155

すでにデータを追加した列を編集しようとしていると思います。そのため、データを失うことなく、列を削除して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;');
}

1つの注意点は、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;');
}

7
Laravel 4の場合は、交換するqueryことにより、statement
レイザー

2
@Razorに感謝します。それに応じて私の答えを更新しました。
Unnawut 2014年

1
down2番目のコードブロック内の関数、SQLステートメントがで終わる必要がありますNOT NULL。(down3番目の例の関数は正しいです。)
Scott Weldon

46

彼は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です。


16

列を変更して偶然見つけた場合

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

次に、インストールします

composer require doctrine/dbal


1
このビットは私、私は先に行って、従うことが容易に例外/ソリューションを作ったので:github.com/laravel/framework/pull/10002
ボーSimensen

9

Laravel 5+については、Dmitri Chebotarevの回答に追加。

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

3

Dmitri Chebotarev Answerに追加して、

一度に複数の列を変更したい場合は、以下のように行うことができます

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


2

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;');
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.