Thay đổi di chuyển của Laravel để tạo một cột không thể xóa


194

Tôi đã tạo một di chuyển với không dấu user_id. Làm thế nào tôi có thể chỉnh sửa user_idtrong một di chuyển mới để làm cho nó 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();
}

Câu trả lời:


262

Laravel 5 hiện hỗ trợ thay đổi một cột; đây là một ví dụ từ tài liệu chính thức:

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

Nguồn: http://laravel.com/docs/5.0/schema#changing-columns

Laravel 4 không hỗ trợ sửa đổi các cột, vì vậy bạn sẽ cần sử dụng một kỹ thuật khác như viết lệnh SQL thô. Ví dụ:

// 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 cho điều này. Nhưng làm thế nào tôi có thể làm ngược lại? Làm thế nào để thay đổi một cột để không có giá trị? Có ý kiến ​​gì không?
algorardi

@algorardi Bạn có thử chuỗi '$ t-> (' name ', 100) -> change ();'
MURATSPLAT

7
Bạn cần yêu cầu học thuyết \ dbal để di chuyển
younes0

33
@algorardi ->nullable(false)sẽ cho phép bạn thay đổi cột trở lại một lần nữa.
Colin

9
-> thay đổi () yêu cầu bạn cài đặt gói Doctrine DBAL và vốn không nhận ra tất cả các loại cột giống nhau có sẵn từ laravel .. ví dụ: double không phải là loại cột được nhận dạng cho DBAL.
Will Vincent

174

Đây là câu trả lời đầy đủ cho người đọc trong tương lai. Lưu ý rằng điều này chỉ có thể có trong Laravel 5+.

Trước hết bạn sẽ cần gói học thuyết / dbal :

composer require doctrine/dbal

Bây giờ trong di chuyển của bạn, bạn có thể làm điều này để làm cho cột không thể:

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

Bạn có thể tự hỏi làm thế nào để hoàn nguyên hoạt động này. Đáng buồn là cú pháp này không được hỗ trợ:

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

Đây là cú pháp đúng để hoàn nguyên việc di chuyển:

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

Hoặc, nếu bạn thích, bạn có thể viết một truy vấn thô:

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

Hy vọng bạn sẽ thấy câu trả lời này hữu ích. :)


3
Đây là câu trả lời đầy đủ nhất cho L5, nhưng nên đề cập rằng nếu 'user_id' là khóa ngoại, thì bạn sẽ không thể thay đổi nó trừ khi bạn chạy 'DB :: statement (' SET FOREIGN_KEY_CHECKS = 0 ');' Đầu tiên. Và đặt nó trở lại 1 khi bạn hoàn thành.
rzb

1
Cảm ơn bạn, nullable(false)đã cứu tôi khỏi nhổ tóc của tôi, bởi vì nullable()tài liệu không tốt, và không có notNull()chức năng.
Zack Morris

Điều này không làm việc cho các khóa ngoại với postgres. cố gắng SET FOREIGN_KEY_CHECKS = 0đưa ra một lỗi. bạn có thể sẽ cần phải thay đổi các ràng buộc của bảng bằng cách sử dụng truy vấn thô. xem tại đây: postgresql.org/docs/civerse/static/sql-altertable.html
rrrafalsz

Điều này đang phá vỡ các bài kiểm tra của tôi. Các bài kiểm tra bắt đầu chạy và sau đó treo. Tôi cho rằng rollback đầu tiên gây ra điều này. Nguyên nhân treo các bài kiểm tra cho MySQL cũng như cho SQLite.
Thomas Praxl

155

Tôi giả sử rằng bạn đang cố gắng chỉnh sửa một cột mà bạn đã thêm dữ liệu vào, vì vậy việc bỏ cột và thêm lại dưới dạng cột không thể thực hiện được là không thể thực hiện được mà không mất dữ liệu. Chúng tôi sẽ altercột hiện tại.

Tuy nhiên, trình xây dựng lược đồ của Laravel không hỗ trợ sửa đổi các cột ngoài việc đổi tên cột. Vì vậy, bạn sẽ cần chạy các truy vấn thô để thực hiện chúng, như thế này:

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

Và để đảm bảo bạn vẫn có thể quay lại quá trình di chuyển của mình, chúng tôi cũng sẽ làm down()như vậy.

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

Một lưu ý là vì bạn đang chuyển đổi giữa nullable và không nullable, bạn sẽ cần đảm bảo rằng bạn dọn sạch dữ liệu trước / sau khi di chuyển. Vì vậy, làm điều đó trong tập lệnh di chuyển của bạn cả hai cách:

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
Đối với Laravel 4, thay thế querybằngstatement
Dao cạo

2
Cảm ơn @Razor. Cập nhật câu trả lời của tôi cho phù hợp.
Vô song

1
Trong downhàm trong khối mã thứ hai, câu lệnh SQL sẽ kết thúc bằng NOT NULL. ( downHàm trong ví dụ thứ ba là chính xác.)
Scott Weldon

46

Anh ấy là người di cư đầy đủ cho 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();
    });
}

Vấn đề là, bạn có thể loại bỏ nullable bằng cách chuyển falsenhư một đối số.


16

Nếu bạn tình cờ thay đổi các cột và vấp ngã

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

sau đó chỉ cần cài đặt

composer require doctrine/dbal


1
Điều này hơi cho tôi vì vậy tôi đã đi trước và làm cho ngoại lệ / giải pháp dễ theo dõi hơn: github.com/laravel/framework/pull/10002
Beau Simensen

9

Thêm vào câu trả lời của Dmitri Chebotarev, như đối với Laravel 5+.

Sau khi yêu cầu gói giáo lý / dbal :

composer require doctrine/dbal

Sau đó, bạn có thể thực hiện di chuyển với các cột không thể, như vậy:

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

Để hoàn nguyên thao tác, hãy làm:

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

Thêm vào Dmitri Chebotarev Trả lời,

Nếu bạn muốn thay đổi nhiều cột cùng một lúc, bạn có thể làm như dưới đây

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

Thử nó:

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

1
Nó không thay đổi cột hiện tại
dVaffection

9
->changecuối cùng bạn đã quên và chỉ đề cập đến nó Laravel 5+
Alexander Malakhov

Bạn cần phải yêu cầucomposer require doctrine/dbal
Lizesh Shakya

2

Đối với Laravel 4.2, câu trả lời của Unnawut ở trên là câu trả lời hay nhất. Nhưng nếu bạn đang sử dụng tiền tố bảng, thì bạn cần thay đổi mã của mình một chút.

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

Và để đảm bảo bạn vẫn có thể quay lại quá trình di chuyển của mình, chúng tôi cũng sẽ làm down()như vậy.

function down()
{
    $table_prefix = DB::getTablePrefix();
    DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.