对同一关系使用contains方法后,Laravel belongsToMany attach()方法不起作用
我正在我的项目中进行友谊实现,但除了只添加朋友外,我希望像facebook一样拥有邀请功能,我使用多对多自引用方法 数据透视表架构:对同一关系使用contains方法后,Laravel belongsToMany attach()方法不起作用,laravel,many-to-many,Laravel,Many To Many,我正在我的项目中进行友谊实现,但除了只添加朋友外,我希望像facebook一样拥有邀请功能,我使用多对多自引用方法 数据透视表架构: Schema::create('user_friends', function (Blueprint $table) { $table->primary(['user_id', 'friend_id']); $table->unsignedInteger('user_id'); $table-&g
Schema::create('user_friends', function (Blueprint $table) {
$table->primary(['user_id', 'friend_id']);
$table->unsignedInteger('user_id');
$table->unsignedInteger('friend_id');
$table->timestamps();
$table->timestamp('accepted_at')->nullable()->default(null);
$table->timestamp('refused_at')->nullable()->default(null);
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
$table->foreign('friend_id')
->references('id')->on('users')
->onDelete('cascade');
});
我将朋友/成为朋友分为3组:
class User {
//
/**
* Friendships that started by the user
*/
public function friendsOfMine()
{
return $this->belongsToMany('App\User', 'user_friends', 'user_id', 'friend_id')
->withPivot(['accepted_at', 'refused_at'])
->wherePivot('accepted_at', '<>', null)
->withTimestamps();
}
/**
* Friendships that started by others
*/
public function friendOfOthers()
{
return $this->belongsToMany('App\User', 'user_friends', 'friend_id', 'user_id')
->withPivot(['accepted_at', 'refused_at'])
->wherePivot('accepted_at', '<>', null)
->withTimestamps();
}
// accessor allowing you call $user->friends
public function getFriendsAttribute()
{
if (!array_key_exists('friends', $this->relations)) {
$this->loadFriends();
}
return $this->getRelation('friends');
}
protected function loadFriends()
{
if (!array_key_exists('friends', $this->relations)) {
$friends = $this->mergeFriends();
$this->setRelation('friends', $friends);
}
}
protected function mergeFriends()
{
return $this->friendsOfMine->merge($this->friendOfOthers);
}
第3组:邀请者:
/**
* Users that invite this user as friend.
*/
public function invitors()
{
return $this->belongsToMany('App\User', 'user_friends', 'friend_id', 'user_id')
->withPivot(['accepted_at', 'refused_at'])
->wherePivot('accepted_at', null)
->withTimestamps();
}
然后,当我想邀请一个新用户时,我想确保这个新用户不属于以下3个组:
public function inviteFriend(User $user)
{
if (!$this->is($user) &&
!$this->friends->contains($user) &&
!$this->invitees->contains($user) &&
!$this->invitors->contains($user)) {
$this->invitees()->attach($user);
}
}
然后出现了一个奇怪的问题,我使用dd()来检查进度,并确认条件是正确的和正确的
$this->invitees()->attach($user);
已执行,但未正确添加$user,
但是,如果我删除这一个条件检查(不是另一个)
并且函数变得
public function inviteFriend(User $user)
{
if (!$this->is($user) &&
!$this->friends->contains($user) &&
// !$this->invitees->contains($user) &&
!$this->invitors->contains($user)) {
$this->invitees()->attach($user);
}
}
然后它将正常工作,但是,随后可能会重复邀请同一个人,然后导致SQL约束冲突
有人能帮我解决这个问题吗?提前谢谢你 您可以使用syncWithoutDetaching而不是attach功能:
public function inviteFriend(User $user)
{
if (!$this->is($user) &&
!$this->friends->contains($user) &&
!$this->invitors->contains($user)) {
$this->invitees()->syncWithoutDetaching([$user->id]);
}
}
这个函数如果不存在就附加用户id经过更多的搜索,我终于找到了一个解决问题的方法,我认为这种方法在效率方面可能比我原来的方法要好,因为对于这种情况,
collection->contains()
if (!$this->is($user) &&
!$this->friendsOfMine()->wherePivot('friend_id', $user->id)->exists() &&
!$this->friendOfOthers()->wherePivot('user_id', $user->id)->exists() &&
!$this->invitees()->wherePivot('friend_id', $user->id)->exists() &&
!$this->invitors()->wherePivot('user_id', $user->id)->exists()) {
$this->invitees()->attach($user);
}
谢谢你的回复,我尝试了你的建议,但是得到的结果和我原来的代码一样。
public function inviteFriend(User $user)
{
if (!$this->is($user) &&
!$this->friends->contains($user) &&
!$this->invitors->contains($user)) {
$this->invitees()->syncWithoutDetaching([$user->id]);
}
}
if (!$this->is($user) &&
!$this->friendsOfMine()->wherePivot('friend_id', $user->id)->exists() &&
!$this->friendOfOthers()->wherePivot('user_id', $user->id)->exists() &&
!$this->invitees()->wherePivot('friend_id', $user->id)->exists() &&
!$this->invitors()->wherePivot('user_id', $user->id)->exists()) {
$this->invitees()->attach($user);
}