2015-07-03 4 views
5

Прежде всего, я хочу вам сказать, я искал в Интернете эту проблему, и я не смог решить эту проблему.CONSTRAIN Unique на Laravel 5 Schema Builder

Моя проблема связана с основными ключами моих таблиц.

У меня есть 2 таблицы, события и event_guest

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

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

Каждое событие имеет много event_guest, но адрес электронной почты каждого гостя должно быть уникальным в каждом случае.

На мой контроллер я хочу получить или создать с помощью метода firstOrCreate на EventGuest Модель:

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

Если сообщение электронной почты не установлен на событии он должен записать запись.

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

Что мне нужно это eventid в качестве первичного ключа и guestid в auto_increment поле, так что можно сбросить до 1 на каждое событие. Например:

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

А также мне нужна электронная почта как уникальное поле для предотвращения дублирования строк.

В настоящее время я использую Laravel 5 Миграции, но когда я пытаюсь сбросить первичные поля он запрашивает эту ошибку:

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

Это мой код переноса:

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

      }); 

мне действительно нужна помощь чтобы понять это правильно.

У меня не было никаких проблем в прошлом с помощью:

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 

Теперь

+1

Можно ли разбить идентификатор гостя, имя, фамилию и адрес электронной почты в их собственную таблицу, называемую «гость». Затем измените схему «event_guest» только на event_id и guest_id? –

ответ

2

Есть 2 проблемы с вашей миграции кода, которые мешают вам от создания таблицы вам нужно.

Прежде всего, двигатель MySQL по умолчанию - InnoDB, который запрещает автоинкремент на составных первичных ключах. Таким образом, вам необходимо установить двигатель явно MyISAM:

$table->engine = 'MyISAM'; 

Во-вторых, при установке колонки на автоматическое приращение, схема строитель Laravel предполагает, что первичный ключ и делает этот столбец первичный ключ при создании создать заявление , Поэтому, когда следующий запрос пытается определить составной первичный ключ, уже существует первичный ключ на столбце guestid - следовательно, повторяется ошибка первичного ключа.

Решение этой проблемы заключается в том, чтобы определить guestid как стандартный целочисленный столбец, создать составной ключ, а затем обновить столбец «гость», чтобы он был автоинкрементным. К сожалению, построитель схем не поддерживает никаких других операций, отличных от переименования, поэтому вам необходимо использовать базовый уровень БД и выполнить необработанный запрос.

Подводя итог, код миграции должен выглядеть следующим образом:

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

Мне нужно было изменить $ table-> unique (array ('email', 'name')); для $ table-> unique (array ('guestid', 'email')); и я был хорош, чтобы пойти! ... –

3

Я понимаю, что вы просите. Но я думаю, что вы создаете слишком много избыточности в своей базе данных. Ваша ситуация влияет на отношения ManyToMany между событием и гостем. Что я верю, будет в значительной степени упрощать вашу проблему. Поэтому я представляю другое решение из того, что вы просите.

В вашей проблеме Event может иметь много Guest с, и Guest могут принадлежать ко многим Event с. Мы можем представить это в Laravel 5. *, как показано ниже,

миграции и модель 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'); 
    } 

} 

миграции и модели для 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'); 
    } 

} 

миграции для 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'); 
}); 

Теперь подписавшись Guest к Event так же легко, как показано ниже

$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 

В этом stetagy, вы можете отделить event и guest данные специальных таблиц без дублирования и поддерживать ограничения уникальности очень легко. И вы, , создаете сводную таблицу, чтобы поддерживать свои отношения.

Read More о Laravel Отношения.

+0

Большое спасибо за ваш ответ, я начал этот проект таким образом, создавая отдельные таблицы и делая отношения, очень логичен и хорошо написан. Проблема с ограничениями в моем приложении заключается в том, что в прошлом меня также просили учитывать зарегистрированных пользователей, чтобы быть частью гостей мероприятия ... поэтому проблемы начались, когда я перенес приложение в laravel, чтобы сохранить структуру db и данных, мне пришлось создавать миграции, как в другой базе данных. +1 Я бы порекомендовал ваш подход к другим пользователям и передовой практике, но предложение jedrzej.kurylo работало для меня в этом случае! –

Смежные вопросы