0

Lets say you have User and Friend Schemas

user:
   - id
   - username

friends:
   - id
   - user_id
   - friend_id

A 'friendship' is determined by having two reciprocal records. And lets says if it's just a one way relationship, this is a pending request. So in the friends table:

user_id: 5 | friend_id: 6
user_id: 6 | friend_id 5

In the User Model, you would then have:

public function friends()
    {
        return $this->belongsToMany(self::class,'friends','user_id','friend_id')->withTimestamps();
    }

However, this isn't the whole story because this doesn't check for the presence of the mutual relationship.

How would you set this up? Should the friends() method be responsible for for querying the data further? Or is this method appropriate, and instances where you want to get a mutual friendship, you should append a query scope? For example

$this->user->friends->mutual()

OR

$this->user->friends->pending()
djt
  • 7,297
  • 11
  • 55
  • 102

1 Answers1

0

Ended up figuring this out based on this answer. However, i changed the merge() functionality to intersect() because I'm not use the approved flag to determine weather the friendship is mutual. I'm only using the presence of the two relationships.

So in my case. the relations are:

public function myFriends()
{
    return $this->belongsToMany(self::class,'friends','user_id','friend_id')->withTimestamps();
}

public function friendsOf()
{
    return $this->belongsToMany(self::class,'friends','friend_id','user_id')->withTimestamps();
}

And the other logic is:

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)) $this->setRelation('friends', $this->mergeFriends());
}

protected function mergeFriends()
{
    return $this->myFriends->intersect($this->friendsOf);
}
Community
  • 1
  • 1
djt
  • 7,297
  • 11
  • 55
  • 102