首先,我想告诉你,我已经在互联网上搜索了这个问题,但我无法解决这个问题。
我的问题在于表格的主键。
我有2个表,事件和 event_guest
+-----------+
| event |
+-----------+
| eventid |
+-----------+
+-------------+
| event_guest |
+-------------+
| guestid |
| eventid |
| firstname |
| lastname |
| email |
+-------------+
每个活动都有很多event_guest
,但每个活动的电子邮件在每个活动中都必须是唯一的。
在我的控制器上,我想通过在EventGuest模型上使用firstOrCreate方法获取或创建:
EventGuests::firstOrCreate(['eventid' => $eventid,'firstname' => 'Ivan', 'lastname'=>'Bravo', 'email'=>'ivnbrv@mac.com');
如果未在事件中设置电子邮件,则必须记录该条目。
+-----------+----------+-----------+-----------+----------------+
| guestid | eventid | firstname | lastname | email |
+-----------+----------+-----------+-----------+----------------+
| 1 | 1 | Ivan | Bravo | ivnbrv@mac.com |
+-----------+----------+-----------+-----------+----------------+
我需要的是eventid
作为主键,guestid
作为auto_increment
字段,因此它可以在每个事件中重置为1。例如:
+-----------+----------+-----------+-----------+----------------+
| guestid | eventid | firstname | lastname | email |
+-----------+----------+-----------+-----------+----------------+
| 1 | 1 | Ivan | Bravo | ivnbrv@mac.com |
| 2 | 1 | John | Doe | test@mac.com |
| 1 | 2 | Ivan | Bravo | ivnbrv@mac.com |
+-----------+----------+-----------+-----------+----------------+
并且我还需要电子邮件作为唯一字段以防止重复行。
目前我正在使用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
现在
答案 0 :(得分:3)
我理解你的要求。但我认为您在数据库中创建了太多冗余。你的情况要警惕Event和Guest之间的许多关系。我相信,会在很大程度上简化你的问题。所以我提出了一个与你所要求的不同的解决方案。
在您的问题中,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
在这种方法中,您可以将event
和guest
数据分离到专用表中而不会重复,并且可以非常轻松地维护唯一性约束。你呢
创建数据透视表以维护他们的关系。
Read More关于Laravel Relationships。
答案 1 :(得分:2)
迁移代码存在两个问题,导致您无法创建所需的表格。
首先,默认的MySQL引擎是InnoDB,它不允许在复合主键上自动增加。因此,您需要将引擎显式设置为MyISAM:
$table->engine = 'MyISAM';
其次,当您将列设置为自动递增时,Laravel的架构构建器会假定它是主键,并在生成create语句时将该列作为主键。因此,当下一个查询尝试定义复合主键时,guestid列上已存在主键 - 因此存在重复的主键错误。
该问题的解决方案是将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');