2013-06-04 27 views
25

Tôi vừa mới tạo một dự án Laravel 4 mới và đang tìm những điều kỳ lạ xảy ra với khía cạnh khóa ngoài của trình tạo lược đồ. Nếu tôi sử dụng phương pháp ->foreign() trong bất kỳ di chuyển nào của tôi, tôi nhận được lỗi MySQL 150 và lỗi chung 1005. Theo tài liệu tại laravel.com/docs, hai kịch bản ở dưới cùng sẽ hoạt động? Có ai biết tại sao họ không?Các khóa ngoài trong vấn đề di trú Laravel 4

Sau đây không làm việc:

Schema::create('areas', function($table) 
    { 
     $table->engine ='InnoDB'; 
     $table->increments('id'); 

     $table->integer('region_id')->references('id')->on('regions'); 

     $table->string('name', 160); 
     $table->timestamps(); 
    }); 

Nhưng hai không làm việc:

Schema::create('areas', function($table) 
    { 
     $table->engine ='InnoDB'; 
     $table->increments('id'); 

     $table->foreign('region_id')->references('id')->on('regions'); 

     $table->string('name', 160); 
     $table->timestamps(); 
    }); 

    Schema::create('areas', function($table) 
    { 
     $table->engine ='InnoDB'; 
     $table->increments('id'); 

     $table->integer('region_id'); 
     $table->foreign('region_id')->references('id')->on('regions'); 

     $table->string('name', 160); 
     $table->timestamps(); 
    }); 
+0

bản sao có thể có của [Di chuyển Laravel 4 ném 1072 lỗi] (http://stackoverflow.com/questions/16928032/laravel-4-migrations-throwing-1072-error) –

+4

Câu hỏi này là về lý do tại sao 't làm việc, khác là về lỗi 1072 MySQL. – JasonMortonNZ

+0

Chỉ cần tham gia vào Laravel và nhấn nó. Cách giải quyết của tôi là thêm các khóa ngoại bằng cách sử dụng một sự di trú riêng biệt. Nó hoạt động nhưng cảm thấy sai. – joemaller

Trả lời

53

Kiểm tra loại id của bạn. Laravel 4 tạo ra một id gia tăng với một int (10) unsigned. Nếu bạn tạo một số nguyên cơ bản và cố gắng đặt một khóa ngoại vào nó, nó sẽ thất bại.

Như được đề xuất trong tài liệu tại this link, bạn nên tạo id nước ngoài với $table->unsignedInteger(YOUR_ID_NAME); để làm cho nó hoạt động.

+5

Ví dụ: (sử dụng bảng) '$ Bảng-> increments ('id');' và (viết bảng) '$ Bảng-> unsignedInteger ('user_id'); \ n' $ Bảng-> nước ngoài ('user_id' ') -> tài liệu tham khảo (' id ') -> trên (' người '); ' – alairock

+0

tôi đã sử dụng đúng loại như vậy' $ Bảng-> số nguyên (' user_id ') -> unsigned(); 'Và unsigned tài sản đã được thiết lập trong DB nhưng nó đã không làm việc cho tôi. Tôi cập nhật mã của tôi để sử dụng 'unsignedInteger' và tất cả mọi thứ bây giờ hoạt động đáng ngạc nhiên –

+0

Đã có cùng một vấn đề bản thân mình - Dayle Rees đã giải thích nó tốt (với ví dụ) http://daylerees.com/codebright/eloquent-relationships –

2

Nó hoạt động, nhưng đôi khi bạn chỉ cần phải cẩn thận và cố gắng hiểu những gì đang xảy ra đằng sau bối cảnh.

Như tôi đã nói trong nhận xét của mình. Khi bạn lần đầu tiên chạy di chuyển mà không tạo cột liên quan, các dịch vụ di trú Laravel đã tạo bảng của bạn và sau đó, khi bạn cố di chuyển lại, nó sẽ luôn báo lỗi rằng bảng đã tồn tại.

Vì vậy, bạn chỉ cần drop table areas và chạy lại php artisan migrate để khắc phục tất cả.

EDIT:

Tôi vừa tạo di chuyển của bạn (bên dưới) tại đây và hoạt động.

Như bạn có thể thấy tôi không sử dụng MySQL, do đó, nó phải là một vấn đề MySQL. Kiểm tra tài liệu khóa ngoài của MySQL để xem liệu siêu dữ liệu của bạn có phù hợp với các yêu cầu của InnoDB không: http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html.

<?php 

use Illuminate\Database\Migrations\Migration; 

class CreateAreasTable extends Migration { 

    /** 
    * Run the migrations. 
    * 
    * @return void 
    */ 
    public function up() 
    { 
     Schema::create('regions', function($table) 
     { 
      // $table->engine = 'InnoDB'; 
      $table->increments('id'); 
      $table->string('name', 160)->unique(); 
      $table->timestamps(); 
     }); 

     Schema::create('areas', function($table) 
     { 
      // $table->engine ='InnoDB'; 
      $table->increments('id'); 

      $table->integer('region_id'); 
      $table->foreign('region_id')->references('id')->on('regions'); 

      $table->string('name', 160); 
      $table->timestamps(); 
     });  
    } 

    /** 
    * Reverse the migrations. 
    * 
    * @return void 
    */ 
    public function down() 
    { 
    Schema::drop('areas'); 
    Schema::drop('regions'); 
    } 

} 

enter image description here

+1

Điều đó không hiệu quả. Tôi đã loại bỏ cơ sở dữ liệu, tạo một cơ sở dữ liệu mới, chạy 'php artisan migration: install', tiếp theo là' php artisan migrate' và các lỗi, vẫn xảy ra, nhưng chỉ khi tôi đưa ra bất kỳ đề cập nào về '-> foreign()'. – JasonMortonNZ

1

antonio carlos là đúng, đảm bảo rằng bạn đã tạo bảng tham chiếu đầu tiên của khóa ngoại.

thử di chuyển đầu tiên các bảng không có khóa ngoài, sau đó thực hiện một di chuyển khác gán khóa ngoài. trên trạng thái này, laravel chắc chắn rằng (các) khóa tham chiếu đã tồn tại. và bạn không phải thả bảng trong các lỗi thủ công.

7

Ngoài ra một số câu trả lời qua tại câu hỏi này "General error: 1005 Can't create table" Using Laravel Schema Build and Foreign Keys

Tóm tắt các câu trả lời liệt kê ở đó, bao gồm cả tôi:

  1. Keys nước ngoài thường yêu cầu InnoDB, sau đó thiết lập cơ mặc định của bạn, hoặc chỉ định rõ $table->engine = 'InnoDB'; Nếu bảng của bạn đã được tạo và đã được đặt mặc định thành MyISAM, bạn có thể cần thay đổi nó.

  2. Khóa ngoài yêu cầu bảng được tham chiếu tồn tại. Đảm bảo bảng được tham chiếu được tạo trong quá trình di chuyển trước đó, trước khi tạo khóa. Xem xét việc tạo các khóa trong một di chuyển riêng biệt để chắc chắn.

  3. Khóa ngoại yêu cầu loại dữ liệu phải đồng dư. Kiểm tra xem trường được tham chiếu có cùng loại hay không, cho dù đó là trường đã ký hay chưa ký, cho dù chiều dài của nó là giống nhau (hoặc ít hơn).

  4. Nếu bạn đang chuyển đổi giữa quá trình di chuyển mã hóa bằng tay và sử dụng trình tạo, hãy đảm bảo bạn kiểm tra loại id bạn đang sử dụng. Artisan sử dụng các biến số () theo mặc định nhưng Jeffrey Way dường như thích số nguyên ('id', true).

+1

Vấn đề của tôi là nó đã được tạo ra trước đó và đã được mặc định là MyISAM. Sau khi cập nhật bảng đang được tham chiếu đến InnoDB mọi thứ đã hoạt động rất tốt. –

5

Có cùng vấn đề ngày trước.

Gốc của sự cố là: cột có khóa ngoài phải cùng loại với khóa đó. Và bạn có các loại khác nhau: INT/unsigned int

điều này làm cho id một UNSIGNED INT

$table->increments('id'); 

và điều này làm region_id một INT

$table->integer('region_id')->references('id')->on('regions'); 

Để giải quyết điều này, hãy region_id một UNSIGNED INT quá

$table->integer('region_id')->unsigned()->references('id')->on('regions'); 
           ^^^^^^^^^ note here 

Tài liệu về Laravel có mention về điều này:

Lưu ý: Khi tạo một khóa ngoại tham chiếu đến một số nguyên incrementing, hãy nhớ luôn luôn làm cho cột khóa ngoại unsigned.