4

There are 3 tables:

users: id, name

compliments: id, name

users_compliments: id, compliment_id, user_id, complimentor_id

Here is my User model:

class User extends Model
    public function sent_compliments()  {  
        return 
            $this->belongsToMany(
            'Compliment', 
            'users_compliments', 
            'complimentor_id',
            'compliment_id'
         )->withPivot('user_id');
}

here is an example response if I run $user->sent_compliments()->get()

Illuminate\Database\Eloquent\Collection {
     all: [
       Compliment {
         id: 2,
         name: "You are smart",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {
           user_id: 6,
           id: 99,
         },
       },
       Compliment {
         id: 52,
         name: "You are funny",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {
           user_id: 42,
           id: 186,
         },
       },
     ],
   }

but here is the response I want (it includes the actual User model instead of just the user_id in the pivot)

Illuminate\Database\Eloquent\Collection {
     all: [
       Compliment {
         id: 2,
         name: "You are smart",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {
           user_id: 6,
           id: 99,
         },
         user {
             id: 6,
             name: "John"
         }
       },
       Compliment {
         id: 52,
         name: "You are funny",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {
           user_id: 42,
           id: 186,
         },
           user {
             id: 42,
             name: "Alex"
         }
       },
     ],
   }

Is there a way to get this data with an eloquent eager load (like using the With:: command ) instead of iterating through the pivot, collecting the user_ids and manually querying the User table?

Yaseen Aniss
  • 151
  • 1
  • 9
  • please show `sent_nominations` method – Alihossein shahabi Jul 03 '18 at 10:55
  • The `sent_compliments` method is posted in the question above. It's in the `User` model. `public function sent_compliments()` @Alihosseinshahabi – Yaseen Aniss Jul 03 '18 at 10:57
  • @Alihosseinshahabi sorry, there was a typo in my question. `sent_nominations` does not exist. It should be `sent_compliments` ... I just updated the question and I apologize for the confusion – Yaseen Aniss Jul 03 '18 at 10:59

1 Answers1

2

You need to define pivot class and add relation belongsTo to pivot model for user_id

User Model

public function sent_compliments()  {  
    return 
        $this->belongsToMany(
        'Compliment', 
        'users_compliments', 
        'complimentor_id',
        'compliment_id'
     )->withPivot('user_id')->using('App\UserComplement');
}

Pivot model use Illuminate\Database\Eloquent\Relations\Pivot;

class UserComplement extends Pivot {
    protected $table = 'users_compliments';

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

Feth data

//if you have user instance already then
$complements = $user->sent_compliments;

//if you don't have fetched user yet then try this 
$user = User::with('sent_compliments')->find($userId);
$complements = $user->sent_compliments;

foreach($complements as $complement){
    dd($complement);
    dd($complement->pivot->user);
}

For details check this Defining Custom Intermediate Table Models https://laravel.com/docs/5.6/eloquent-relationships#many-to-many

EDIT

As @JonasStaudenmeir pointed, there is no way to eager load pivot user relationship. Here is another solution

User Model

public function sent_compliments()  {  
    return $this->hasMany(UserCompliment::class , 'complimentor_id');
}

UserComplement model

class UserComplement extends Model {
    $table = 'users_compliments';

    public function complimentor()  {  
        return $this->belongsTo(User::class , 'complimentor_id');
    }

    public function complement()  {  
        return $this->belongsTo(Compliment::class , 'compliment_id');
    }

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

Fetch Data

$user = User::with('sent_compliments','sent_compliments.complement', 'sent_compliments.user')->find($userId);
$sentComplements = $user->sent_compliments;

foreach($sentComplements as $sentComplement){
    dd($sentComplement->complement);
    dd($sentComplement->user);
}

Hope it may clear you

rkj
  • 8,067
  • 2
  • 27
  • 33
  • thanks for your help, but this didn't work... the one and only difference is that the response now says `pivot: UserNominationPivot` instead of `pivot: Illuminate\Database\Eloquent\Relations\Pivot` ... but the `user` model is still not in the response – Yaseen Aniss Jul 03 '18 at 11:18
  • you have imported wrong `Pivot` class, it is a tested code. let me add the pivot import class there – rkj Jul 03 '18 at 11:19
  • i have added import, use it in your code and then try – rkj Jul 03 '18 at 11:23
  • how did you fetch the `User` model ? – rkj Jul 03 '18 at 11:24
  • you must have to create `UserComplement` class with extending `Pivot` and add it in relation like this `->using('App\UserComplement');' – rkj Jul 03 '18 at 11:38
  • There is no way to eager load the `user` relationship. – Jonas Staudenmeir Jul 03 '18 at 13:14
  • @JonasStaudenmeir thanks for pointing, i have updated with alternative solution – rkj Jul 04 '18 at 06:06