我正在我的项目中实现友谊实现,但是除了只添加朋友外,我还希望像facebook一样具有邀请功能,我使用了许多对自我引用的方法,
数据透视表模式:
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组:
以下是其对应的代码:
第1组:朋友:
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);
}
第2组:受邀者:
/**
* Users that are invited as friends by this user.
*/
public function invitees()
{
return $this->belongsToMany('App\User', 'user_friends', 'user_id', 'friend_id')
->withPivot(['accepted_at', 'refused_at'])
->wherePivot('accepted_at', null)
->withTimestamps();
}
第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尚未正确添加, 但是如果我删除了这一项条件检查(而不是另一项)
!$this->invitees->contains($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约束。
有人可以帮助我吗?预先谢谢你!
答案 0 :(得分:1)
您可以使用syncWithoutDetaching代替附加功能:
public function inviteFriend(User $user)
{
if (!$this->is($user) &&
!$this->friends->contains($user) &&
!$this->invitors->contains($user)) {
$this->invitees()->syncWithoutDetaching([$user->id]);
}
}
该函数附加用户ID(如果不存在)
答案 1 :(得分:0)
经过更多搜索,我终于找到了解决问题的方法,并且我认为这种方法在效率方面可能比我原来的方法更好,因为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);
}