Метод присоединенного метода Laravel ownToMany не работает после использования метода содержит в том же отношении - PullRequest
0 голосов
/ 13 апреля 2019

Я работаю над реализацией дружбы в своем проекте, но в дополнение только к добавлению друзей, мне бы хотелось иметь функцию приглашения, как в Facebook, я использую самозависимый подход "многие ко многим",

pivotсхема таблицы:

    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 ]

1 голос
/ 13 апреля 2019

Вы можете использовать syncWithoutDetaching вместо функции присоединения:

public function inviteFriend(User $user)
{

  if (!$this->is($user) &&
    !$this->friends->contains($user) &&
    !$this->invitors->contains($user)) {

    $this->invitees()->syncWithoutDetaching([$user->id]);  
  }
}

эта функция присоединяет идентификатор пользователя, если не существует

0 голосов
/ 15 апреля 2019

После долгих поисков я, наконец, нашел обходной путь для решения своей проблемы, и я думаю, что этот подход может быть лучше моего первоначального с точки зрения эффективности, поскольку 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);
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...