Bir Sütunu Nullable Hale Getirmek İçin Laravel Migration Değişikliği


208

İmzasız bir göç oluşturdum user_id. Bunu user_idyapmak için yeni bir geçişte nasıl düzenleme yapabilirim 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();
}

Yanıtlar:


285

Laravel 5 artık bir sütunun değiştirilmesini destekliyor; İşte resmi belgelerden bir örnek:

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

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

Laravel 4, sütunların değiştirilmesini desteklemez, bu nedenle ham bir SQL komutu yazmak gibi başka bir teknik kullanmanız gerekir. Örneğin:

// 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
Bunun için teşekkürler. Ama bunun tersini nasıl yapabilirim? Bir sütun null yapılamayacak şekilde nasıl değiştirilir? Herhangi bir fikir?
algorhythm

@algorhythm Bu '$ t-> string (' isim ', 100) -> değiştir ();'
MURATSPLAT

8
Taşımak için doktrine ihtiyacınız var
younes0

35
@algorhythm ->nullable(false), sütunu yeniden değiştirmenize izin verir.
Colin

9
-> change (), Doctrine DBAL paketini kurmanızı gerektirir ve laravel tarafından kutudan çıkarılan tüm aynı sütun türlerini kendiliğinden tanımaz .. örneğin double, DBAL için tanınan bir sütun türü değildir.
Will Vincent

182

İşte gelecekteki okuyucu için tam cevap. Bunun yalnızca Laravel 5+ ile mümkün olduğunu unutmayın.

Öncelikle doktrin / dbal paketine ihtiyacınız olacak :

composer require doctrine/dbal

Artık geçişinizde sütunu null yapılabilir hale getirmek için bunu yapabilirsiniz:

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

Bu operasyonu nasıl geri alacağınızı merak ediyor olabilirsiniz. Maalesef bu sözdizimi desteklenmiyor:

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

Bu, geçişi geri almak için doğru sözdizimidir:

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

Veya isterseniz ham bir sorgu yazabilirsiniz:

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

Umarım bu cevabı faydalı bulursunuz. :)


4
Bu, L5 için en eksiksiz cevaptır, ancak 'user_id' olması gereken bir yabancı anahtar ise, 'DB :: deyimini (' SET FOREIGN_KEY_CHECKS = 0 ');' ilk. Ve işiniz bittiğinde tekrar 1'e ayarlayın.
rzb

1
Teşekkür ederim, nullable(false)beni saçımı çekmekten kurtardı, çünkü nullable()iyi belgelenmemiş ve hiçbir notNull()işlevi yok .
Zack Morris

bu, postgres içeren yabancı anahtarlar için çalışmaz. denemek SET FOREIGN_KEY_CHECKS = 0hata veriyor. büyük bir olasılıkla ham bir sorgu kullanarak tablonun kısıtlamalarını değiştirmeniz gerekecektir. buraya bakın: postgresql.org/docs/current/static/sql-altertable.html
szaman

Bu testlerimi bozuyor. Testler başlar ve sonra asılı kalır. Sanırım ilk geri dönüş buna neden oluyor. MySQL ve SQLite için asılı testlere neden olur.
Thomas Praxl

157

Önceden veri eklemiş olduğunuz bir sütunu düzenlemeye çalıştığınızı varsayıyorum, bu nedenle sütunu bırakıp null yapılabilir bir sütun olarak yeniden eklemek veri kaybetmeden mümkün değildir. Biz altermevcut sütun olacağız .

Ancak, Laravel'in şema oluşturucusu, sütunu yeniden adlandırmak dışında sütunların değiştirilmesini desteklemez. Dolayısıyla, bunları yapmak için aşağıdaki gibi ham sorgular çalıştırmanız gerekecek:

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

Ve taşıma işleminizi hala geri alabileceğinizden emin olmak için biz de yapacağız down().

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

Bir not, null yapılabilir ve null yapılamaz arasında dönüştürme yaptığınız için, geçişinizden önce / sonra verileri temizlediğinizden emin olmanız gerektiğidir. Öyleyse bunu taşıma komut dosyanızda iki şekilde yapın:

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 için, yerine querygörestatement
Jilet

2
Teşekkürler @ Razor. Cevabımı buna göre güncelledim.
2014

1
Gelen downikinci kod bloğunda fonksiyonu, SQL deyimi ile sona ermelidir NOT NULL. ( downÜçüncü örnekteki işlev doğrudur.)
Scott Weldon

48

Tam göçünü He're 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();
    });
}

Önemli olan, argüman olarak nullableileterek kaldırabilirsiniz false.


16

Sütunları değiştirir ve tökezlerseniz

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

o zaman sadece kur

composer require doctrine/dbal


1
Bu beni ısırdı, böylece devam ettim ve istisna / çözümü takip etmeyi
Beau Simensen

11

Dmitri Chebotarev'in cevabına Laravel 5+ için ekleniyor.

Doktrin / dbal paketini talep ettikten sonra :

composer require doctrine/dbal

Daha sonra null yapılabilir sütunlarla bir geçiş yapabilirsiniz, örneğin:

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

İşlemi geri almak için şunları yapın:

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 Cevabına ekleniyor,

Bir seferde birden fazla sütunu değiştirmek istiyorsanız, aşağıdaki gibi yapabilirsiniz

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 için, Unnawut'un yukarıdaki cevabı en iyisidir. Ancak tablo öneki kullanıyorsanız, kodunuzu biraz değiştirmeniz gerekir.

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

Ve taşıma işleminizi hala geri alabileceğinizden emin olmak için biz de yapacağız down().

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.