Retrieve related models using hasManyThrough on a pivot table - Laravel 5.7
Asked Answered
N

1

6

I'm trying to retrieve related models of the same type on from a pivot table.

I have 2 models, App\Models\User and App\Models\Group and a pivot model App\Pivots\GroupUser

My tables are have the following structure

users

  • id

groups

  • id

group_user

  • id
  • user_id
  • group_id

I have currently defined relationships as

In app/Models/User.php

public function groups()
{
    return $this->belongsToMany(Group::class)->using(GroupUser::class);
}

In app/Models/Group.php

public function users()
{
    return $this->belongsToMany(User::class)->using(GroupUser::class);
}

In app/Pivots/GroupUser.php

public function user()
{
    return $this->belongsTo(User::class);
}

public function group()
{
    return $this->belongsTo(Group::class);
}

I'm trying to define a relationship in my User class to access all other users that are related by being in the same group. Calling it friends. So far I've tried this:

app/Models/User.php

public function friends()
{
    return $this->hasManyThrough(
        User::class,
        GroupUser::class,
        'user_id',
        'id'
    );
}

But it just ends up returning a collection with only the user I called the relationship from. (same as running collect($this);

I have a solution that does work but is not ideal.

app/Models/User.php

public function friends()
{
    $friends = collect();
    foreach($this->groups as $group) {
        foreach($group->users as $user) {
            if($friends->where('id', $user->id)->count() === 0) {
                $friends->push($user);
            }
        }
    }

    return $friends;
}

Is there a way I can accomplish this using hasManyThrough or some other Eloquent function?

Thanks.

Nigger answered 1/11, 2018 at 1:4 Comment(0)
C
3

You can't do that using hasManyThrough because there is no foreign key on the users table to relate it to the id of the group_user table. You could try going from the user to their groups to their friends using the existing belongsToMany relations:

app/Models/User.php:

// create a custom attribute accessor
public function getFriendsAttribute()
{
    $friends = $this->groups()                                          // query to groups
                    ->with(['users' => function($query) {               // eager-load users from groups
                        $query->where('users.id', '!=', $this->id);     // filter out current user, specify users.id to prevent ambiguity
                    }])->get()
                    ->pluck('users')->flatten();                        // massage the collection to get just the users

    return $friends;
}

Then when you call $user->friends you will get the collection of users who are in the same groups as the current user.

Cooky answered 1/11, 2018 at 1:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.