2015-12-15 17 views
7

Khi chạy di chuyển laravel, tôi đang gặp phải sự bất tiện nhỏ. Tôi sử dụng Laravel 5.1.Di chuyển Laravel cách tốt để vô hiệu hóa các kiểm tra khóa ngoài

Vì có rất nhiều bảng có nhiều mối quan hệ, nên tôi có thể đổi tên tệp di chuyển để chúng chạy đúng thứ tự, do đó không có ràng buộc khoá ngoại nào bị vi phạm. Đây là những gì tôi đã làm một lần trong quá khứ, và nó là rất không thực tế.

Những gì tôi đang làm bây giờ là xác định từng di cư như thế này:

class CreateSomeTable extends Migration 
{ 
    public function up() 
    { 
     DB::statement('SET FOREIGN_KEY_CHECKS=0;'); 
     // my table definitions go here 
     DB::statement('SET FOREIGN_KEY_CHECKS=1;'); 
    } 

    public function down() 
    { 
     DB::statement('SET FOREIGN_KEY_CHECKS=0;'); 
     // drop table 
     DB::statement('SET FOREIGN_KEY_CHECKS=1;'); 
    } 
} 

Vấn đề ở đây là nó tẻ nhạt để viết và nó clutters lên mã. Tôi cũng nghĩ đến việc tạo hai tệp di chuyển giả, mục đích duy nhất của nó là kích hoạt và vô hiệu hóa các kiểm tra khóa ngoài, và tôi sẽ đặt tên chúng theo cách mà chúng chạy ở đầu và cuối của mỗi lần di chuyển.

Nếu có giải pháp thanh lịch, bạn cũng có thể áp dụng nó cho quy trình gieo hạt vì điều này có xu hướng là vấn đề ở đó.

Đây rõ ràng là một giải pháp rất ngẫu hứng, và tôi hỏi liệu có cách nào tốt hơn để làm điều đó không. Có một số phương pháp beforeMigrateafterMigrate mà tôi có thể ghi đè hoặc điều gì đó dọc theo các dòng đó không?

Và nếu không, bạn sẽ làm thế nào?

Mọi thông tin chi tiết sẽ được đánh giá cao, tôi không thích tất cả các tùy chọn tôi đã nêu.

+3

Họ nên luôn luôn chạy theo thứ tự chính xác nếu bạn sử dụng thợ thủ công để tạo ra sự di cư và họ có timestamps đúng . Chúng chạy theo thứ tự các dấu thời gian. – Karl

+1

Vâng, đó là ý của tôi khi được nhắc đến thứ tự tập tin. Vấn đề là, đôi khi bạn không tạo ra chúng đúng thứ tự, hoặc đôi khi bạn có thể có sự phụ thuộc theo chu kỳ tức là cả hai bảng đều có khóa ngoại đề cập đến nhau. Không có vấn đề gì trong thứ tự bạn chạy ví dụ đó, bạn sẽ nhận được một ngoại lệ ràng buộc khóa ngoại trừ khi bạn vô hiệu hóa các kiểm tra. – Pavlin

+4

Cách tốt nhất để tránh vấn đề này là tạo ra một di chuyển với việc tạo bảng đầu tiên và sau đó tạo một/loại bỏ khóa khác. –

Trả lời

9

Tôi đã có một nhiệm vụ tương tự trong tầm tay khi Lumen/Laravel bắt đầu sử dụng Hộ chiếu và tôi đã phải bỏ qua triển khai máy chủ oauth trước đó từ lucadegasperi/oauth2-server-laravel.

Cuối cùng tôi đã xoay sở để có được mọi thứ bằng cách tạo 2 lần di chuyển, nơi đầu tiên xóa khóa ngoại và khóa thứ hai thực sự xóa các bảng.

Tôi đã phải sử dụng ngày trước khi di chuyển Laravel's Passport (2016-06-01) để chúng sẽ được thực thi trước những người đó.

2016_05_31_000000_clear_old_oauth_relations.php

//... 
class ClearOldOauthRelations extends Migration 
{ 
    public function up() 
    { 
     Schema::disableForeignKeyConstraints(); 
     // drop foreign keys 
     Schema::table('oauth_access_tokens', function (BluePrint $table) { 
      $table->dropForeign('oauth_access_tokens_session_id_foreign'); 
     }); 
     //... 
     Schema::enableForeignKeyConstraints(); 
    } 
    //... 
} 

Và trong file thứ hai 2016_05_31_000001_clear_old_oauth.php

//... 
public function up() 
{ 
    Schema::disableForeignKeyConstraints(); 
    Schema::drop('oauth_access_tokens'); 
    //... 
    Schema::enableForeignKeyConstraints(); 
} 
//... 
+0

Điều này thực sự tốt đẹp! Điều này chỉ được thêm vào gần đây, hoặc nó đã được trong laravel một thời gian và tôi chỉ không nhận thấy nó khi tôi đã có vấn đề này? – Pavlin

+0

Xin chào @Pavlin, tôi không biết khi nào điều này được thêm vào trong Laravel/Lumen. Lưu ý rằng bạn sẽ cần tra cứu tên của các ràng buộc khóa ngoại trong ví dụ. PhpMyAdmin (Cấu trúc -> Quan hệ) – 4levels

+0

Điều này đã được thêm vào Laravel kể từ phiên bản 5.2 – arielcr

2

tôi đã thực hiện điều này bằng cách chiết xuất logic chính nước ngoài vào một tập tin chuyển đổi riêng biệt. Điều này đã giúp tôi:

  • Tắt ràng buộc khóa ngoài.
  • Thả cơ sở dữ liệu an toàn, nếu nó tồn tại.

Trong mã:

//file: 2017_06_19_230601_fk_postuser_table.php 

public function down() 
{ 
     Schema::disableForeignKeyConstraints(); 
     Schema::dropIfExists('post_user'); 
} 
0

Một khía cạnh quan trọng cần nhớ là để thả các ForeignKey FIRST, sau đó cột.Thả cột đầu tiên ném các lỗi:

Cannot drop index 'tableName_columnName_foreign': needed in a foreign key constraint

Trình tự các vấn đề thích hợp:

public function down() 
    { 
     Schema::table('tableName', function (Blueprint $table) { 
      $table->dropForeign(['columnName']); // fk first 

      $table->dropColumn('columnName'); // then column 
     }); 
    } 
Các vấn đề liên quan