Laravel对相同关系使用contains方法后,所属ToManyattach()方法不起作用

时间:2019-04-13 01:39:34

标签: laravel many-to-many

我正在我的项目中实现友谊实现,但是除了只添加朋友外,我还希望像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. 已确认的朋友,并且此类别包括我邀请的朋友和邀请我的朋友;
  2. 受邀者:我邀请但未获批准的人;
  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约束。

有人可以帮助我吗?预先谢谢你!

2 个答案:

答案 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);
   }