การย้ายถิ่นของ Laravel เปลี่ยนเป็นทำให้คอลัมน์เป็นโมฆะ


194

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

คำตอบ:


265

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
ขอบคุณสำหรับสิ่งนี้ แต่ฉันจะทำตรงกันข้ามได้อย่างไร จะเปลี่ยนคอลัมน์เป็นโมฆะได้อย่างไร? ความคิดใด ๆ
algorhythm

@algorhythm คุณลอง '$ t-> string (' name ', 100) -> change ();'
MURATSPLAT

7
คุณจำเป็นต้องมีหลักคำสอน \ dbal เพื่อโยกย้าย
younes0

33
@algorhythm ->nullable(false)จะให้คุณเปลี่ยนคอลัมน์อีกครั้ง
โคลิน

9
-> change () ต้องการให้คุณติดตั้งแพ็กเกจ Doctrine DBAL และจะไม่รับรู้ชนิดคอลัมน์เดียวกันทั้งหมดที่มีอยู่ในกล่องจาก laravel .. ตัวอย่างเช่น double ไม่ใช่ประเภทคอลัมน์ที่รู้จักไปยัง DBAL
Will Vincent

175

นี่คือคำตอบที่สมบูรณ์สำหรับผู้อ่านในอนาคต โปรดทราบว่านี่เป็นไปได้เฉพาะใน Laravel 5+

ก่อนอื่นคุณต้องมีหลักคำสอน /แพ็คเกจ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;');
}

หวังว่าคุณจะพบคำตอบนี้มีประโยชน์ :)


4
นี่เป็นคำตอบที่สมบูรณ์แบบที่สุดสำหรับ L5 แต่ควรจะกล่าวว่าหาก 'user_id' เป็นคีย์ต่างประเทศซึ่งควรเป็นคุณจะไม่สามารถเปลี่ยนได้เว้นแต่คุณจะเรียกใช้ 'คำสั่ง DB :: (' 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
โทมัส Praxl

155

ฉันคิดว่าคุณกำลังพยายามแก้ไขคอลัมน์ที่คุณได้เพิ่มข้อมูลไปแล้วดังนั้นการวางคอลัมน์และเพิ่มอีกครั้งเนื่องจากคอลัมน์ที่ไม่มีค่าสามารถทำได้โดยไม่สูญเสียข้อมูล เราจะ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;');
}

สิ่งหนึ่งที่ควรทราบคือเมื่อคุณแปลงระหว่าง nullable และ 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
ขอบคุณ @ มีดโกน อัปเดตคำตอบของฉันตาม
Unnawut

1
ในdownฟังก์ชั่นในรหัสบล็อกที่สองคำสั่ง SQL NOT NULLควรจบลงด้วย ( downฟังก์ชั่นในตัวอย่างที่สามนั้นถูกต้อง)
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
Beau Simensen

9

การเพิ่มคำตอบของ Dmitri Chebotarev สำหรับ Laravel 5+

หลังจากต้องการหลักคำสอน /แพ็คเกจdbal :

composer require doctrine/dbal

จากนั้นคุณสามารถทำการโยกย้ายด้วยคอลัมน์ nullable เช่น:

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 คำตอบ

หากคุณต้องการแก้ไขคอลัมน์หลายคอลัมน์ในเวลาเดียวกันคุณสามารถทำได้เหมือนด้านล่าง

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

ลองมัน:

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

1
ไม่เปลี่ยนคอลัมน์ที่มีอยู่
dVaffection

9
คุณลืม->changeตอนท้ายและพูดถึงมัน Laravel 5+ เท่านั้น
Alexander Malakhov

คุณจำเป็นต้องมีcomposer require doctrine/dbal
Lizesh Shakya

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.