2015-07-03 13 views
5

Trước hết, tôi muốn nói với bạn, tôi đã tìm kiếm trên Internet vấn đề này và tôi đã không thể giải quyết vấn đề này.CONSTRAIN Độc đáo trên Laravel 5 Schema Builder

Vấn đề của tôi là với các khóa chính của bảng.

Tôi có 2 bảng, sự kiệnevent_guest

+-----------+ 
| event  | 
+-----------+ 
| eventid | 
+-----------+ 

+-------------+ 
| event_guest | 
+-------------+ 
| guestid  | 
| eventid  | 
| firstname | 
| lastname | 
| email  | 
+-------------+ 

Mỗi sự kiện có nhiều event_guest, nhưng email của từng khách phải là duy nhất trên mỗi sự kiện.

On điều khiển của tôi tôi muốn có được hoặc tạo ra bằng cách sử dụng phương pháp firstOrCreate trên EventGuest mẫu:

EventGuests::firstOrCreate(['eventid' => $eventid,'firstname' => 'Ivan', 'lastname'=>'Bravo', 'email'=>'[email protected]'); 

Nếu email không được thiết lập về sự kiện này thì phải ghi lại sự xâm nhập.

+-----------+----------+-----------+-----------+----------------+ 
| guestid | eventid | firstname | lastname | email   | 
+-----------+----------+-----------+-----------+----------------+ 
|   1 |  1 | Ivan  | Bravo  | [email protected] | 
+-----------+----------+-----------+-----------+----------------+ 

Những gì tôi cần nó là eventid làm khóa chính và guestid như auto_increment lĩnh vực để nó có thể thiết lập lại tới 1 trên mỗi sự kiện. Ví dụ:

+-----------+----------+-----------+-----------+----------------+ 
| guestid | eventid | firstname | lastname | email   | 
+-----------+----------+-----------+-----------+----------------+ 
|   1 |  1 | Ivan  | Bravo  | [email protected] | 
|   2 |  1 | John  | Doe  | [email protected] | 
|   1 |  2 | Ivan  | Bravo  | [email protected] | 
+-----------+----------+-----------+-----------+----------------+ 

Và tôi cũng cần email làm trường duy nhất để ngăn các hàng trùng lặp.

Hiện nay tôi đang sử dụng Laravel 5 Migrations, nhưng khi tôi cố gắng để thiết lập lại các lĩnh vực chính nó nhắc nhở lỗi này:

Multiple primary key defined (SQL: alter table `event_guest` add primary key event_guest_eventid_guestid_primary(`eventid`, `guestid`))        

Đây là mã di cư của tôi:

Schema::create('event_guest', function(Blueprint $table) { 
       $table->integer('guestid', true); 
       $table->integer('eventid'); 
       $table->integer('contactid')->nullable(); 
       $table->string('firstname', 256); 
       $table->string('lastname', 256); 
       $table->string('email', 256); 
       $table->unique(array('email','name')); 
       $table->primary(array('eventid','guestid')); 

      }); 

tôi thực sự cần sự giúp đỡ để hiểu điều này đúng cách.

tôi đã không gặp khó khăn trong quá khứ sử dụng:

create table `event_guest` (
    `guestid` int(11) NOT NULL AUTO_INCREMENT, 
    `eventid` int(11) NOT NULL DEFAULT '0', 
    `firstname` varchar(255) NOT NULL, 
    `lastname` varchar(255) NOT NULL, 
    `email` varchar(255) NOT NULL, 
    PRIMARY KEY (`eventid`,`guestid`), 
    CONSTRAINT guest UNIQUE (eventid,email) 
) ENGINE=MyISAM 

Bây giờ

+1

Có thể chia nhỏ id khách, tên, họ và email vào bảng riêng của họ có tên là "khách" hay không. Sau đó thay đổi lược đồ 'event_guest' thành event_id và guest_id? –

Trả lời

2

Có 2 vấn đề với mã di cư của bạn mà ngăn cản bạn từ việc tạo bảng mà bạn cần.

Trước hết, công cụ mặc định của MySQL là InnoDB, không cho phép tăng tự động trên các khóa chính kết hợp. Vì vậy, bạn cần phải thiết lập các cơ một cách rõ ràng để MyISAM:

$table->engine = 'MyISAM'; 

Thứ hai, khi bạn thiết lập một cột để tăng tự động, xây dựng sơ đồ Laravel của giả định nó là chìa khóa chính và làm cho cột đó một khóa chính khi tạo tạo ra tuyên bố . Vì vậy, khi truy vấn tiếp theo cố gắng xác định khóa tổng hợp chính đã có khóa chính hiện có trên cột guestid - do đó, lỗi khóa chính trùng lặp.

Giải pháp cho vấn đề đó là xác định guestid là cột số nguyên chuẩn, tạo khóa tổng hợp và sau đó cập nhật cột khách để nó là tự động. Rất tiếc, trình tạo lược đồ không hỗ trợ bất kỳ hoạt động thay đổi nào khác ngoài cột đổi tên, vì vậy bạn cần sử dụng lớp DB cơ bản và thực thi truy vấn thô.

Tóm lại, di chuyển mã của bạn sẽ giống như thế này:

Schema::create('event_guest', function(Blueprint $table) { 
    $table->engine = 'MyISAM'; 
    $table->integer('guestid'); 
    $table->integer('eventid'); 
    $table->integer('contactid')->nullable(); 
    $table->string('firstname', 256); 
    $table->string('lastname', 256); 
    $table->string('email', 256); 
    $table->unique(array('email','name')); 
    $table->primary(array('eventid','guestid')); 
}); 

DB::statement('ALTER TABLE event_guest MODIFY guestid INTEGER NOT NULL AUTO_INCREMENT'); 
+0

tôi chỉ phải thay đổi $ table-> unique (array ('email', 'name')); cho $ table-> unique (mảng ('guestid', 'email')); và tôi đã sẵn sàng! ... –

3

tôi hiểu những gì bạn đang yêu cầu. Nhưng tôi nghĩ bạn đang tạo ra quá nhiều dự phòng trong cơ sở dữ liệu của mình. Tình huống của bạn sẽ gây ra mối quan hệ ManyToMany giữa Sự kiện và Khách. Tôi tin rằng, sẽ mô phỏng vấn đề của bạn ở mức độ lớn. Vì vậy, tôi trình bày một giải pháp khác với những gì bạn đang yêu cầu.

Trong vấn đề của bạn Event có thể có nhiều Guest s, và Guest có thể thuộc về nhiều Event s. Chúng tôi có thể trình bày này trong Laravel 5. * như dưới đây,

Migration và Mô hình Event

Schema::create('events', function(Blueprint $table){ 
    $table->increments('id')->unsigned(); 
    $table->string('title'); 
    $table->string('venue'); 
    $table->text('description'); 
    $table->timestamps(); 
}); 

class Event extends Model{ 

    public function guests(){ 
     return $this->belongsToMany('App\Guest', 'event_guests'); 
    } 

} 

Migration và Mô hình Guest

Schema::create('guests', function(Blueprint $table){ 
    $table->increments('id')->unsigned(); 
    $table->string('email')->unique(); 
    $table->string('password'); 
    $table->string('first_name'); 
    $table->string('last_name'); 
    $table->timestamps(); 
}); 

class Guest extends Model{ 

    public function events(){ 
     return $this->belongsToMany('App\Event','event_guests'); 
    } 

} 

Migration cho event_guests

Schema::create('event_guests', function(Blueprint $table){ 
    $table->increments('id'); 
    $table->integer('event_id')->unsigned();  
    $table->integer('guest_id')->unsigned()->nullable(); 

    $table->foreign('guest_id')->references('id')->on('guests')->onDelete('cascade'); 
    $table->foreign('event_id')->references('id')->on('events')->onDelete('cascade'); 
}); 

Bây giờ đăng ký Guest để Event là dễ dàng như dưới đây

$event = Event::create([ 
      'title' => 'Laracon', 
      'venue' => 'Hotel XYZ, New York', 
      'description' => 'Drink is not free' 
     ]); 
$guest = Guest::findOrFail($guestId); 
$guest2 = Guest::findOrFail($guestId2); 

$event->guests()->sync([$guestId->id, $guestId2->id], false); //`false` as second argument prevents `sync` from detaching previous associations 

Trong stetagy này, bạn có thể tách eventguest dữ liệu vào bảng chuyên dụng mà không cần bất kỳ sự trùng lặp và duy trì ràng buộc duy nhất rất dễ dàng. Và bạn tạo bảng tổng hợp để duy trì các mối quan hệ của chúng.

Read More về mối quan hệ Laravel.

+0

Cảm ơn bạn rất nhiều vì câu trả lời của bạn, tôi bắt đầu dự án này theo cách này, tạo ra các bảng riêng biệt và tạo ra các mối quan hệ, rất hợp lý và được viết tốt. Vấn đề với các ràng buộc trong ứng dụng của tôi là, trong quá khứ tôi đã được yêu cầu xem xét người dùng đã đăng ký, là một phần của khách mời sự kiện ... vì vậy, các vấn đề bắt đầu khi tôi di chuyển ứng dụng sang laravel, để giữ cấu trúc db và dữ liệu, tôi đã phải tạo các di chuyển khi chúng ở trong cơ sở dữ liệu khác. +1 Tôi muốn giới thiệu phương pháp tiếp cận của bạn cho người dùng khác và phương pháp hay nhất, nhưng đề xuất của jedrzej.kurylo đã làm việc cho tôi trong trường hợp này! –

Các vấn đề liên quan