Search code examples
laraveleloquentschemalaravel-5relationships

Stuck on eloquent relationships - pivot and polymorphic relationship


Hello I am stuck on trying to get all comments that belong to a user where a pivot is in between these 2 models. I can't seem to wrap my head around it or my database schema could just be plain wrong. Anyways I would love some help.

Currently my models look like this:

User.php

class User extends Model 
{
    // Grab all the beers that this user has checked in to his personal profile
    public function beers()
    {
        return $this->belongsToMany('App\Beer')->withTimestamps()->withPivot('rating', 'description');
    }
}

Beer.php(pivot relationship)

class Beer extends Model
{
    // polymorphic relationship grab all comments that belong to this beer
    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

Comment.php(set up as polymorphic)

class Comment extends Model
{
    public function commentable()
    {
        return $this->morphTo();
    }

    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

The code here grabs all the comments that belong to a beer pivot record. This works perfectly fine because $user->beers takes into account that we are dealing with a specific user profile and only finds pivot records from the specific $user.

$user = User::find($id);

@foreach($user->beers as $beer)
    @foreach($beer->comments as $comment)
    {{ $comment }}
    @endforeach
@endforeach

Unfortunately the comments relationship only looks at the commentable_id and commentable_type from the comments table and does not take into account the current user_id(the profile we are currently viewing) so when I look at another profile of a user that has the same beer_user pivot combination on his profile the same comments show up there as well.

How can I call the comments relationship of my Beer.php model so that I take into account the user_id as well? Obviously I already added a user_id to my comments table. I've tried to ask this before but I hope by being a bit more detailed this time people can help me out now, I also know how to finally formulate this problem a bit better.

Database:

enter image description here


Solution

  • In this specific code example, I would just use eager loading with a constraint on the user id:

    $user = User::with(['beers', 'beers.comments' => function ($query) use ($id) {
        $query->whereHas('user', function ($query) use ($id) {
            $query->where('id', $id);
        });
    }])->find($id);
    
    @foreach($user->beers as $beer)
        @foreach($beer->comments as $comment)
        {{ $comment }}
        @endforeach
    @endforeach
    

    This eager loading constraint will only work when you have the user's id ahead of time.

    Imagine, however, you weren't able to constrain the eager loading or the query to get the comments. You could still filter the comments Collection after the fact:

    @foreach($user->beers as $beer)
        @foreach($beer->comments->where('user_id', $user->id) as $comment)
        {{ $comment }}
        @endforeach
    @endforeach