• 1
Votes
name
name Punditsdkoslkdosdkoskdo

'with' and 'wherehas' with Laravel Eloquent


Let's say I have three databases, player, credit, and photo, linked with foreign keys:
player
id | name | address

credit
id | player_id | credit_status

photo
id | player_id

Say I want to get all players who has credit_status $status, I'd do it like this:

$status = 'bar';
Player::with('photo','credit')->whereHas('credit', function ($q) use ($status) {
            $q->where('credit_status', $status)->with('credit_status');
        })->paginate(15);

This will lists all players who has credit_status $credit, but it still lists all credits by that player regardless of the status.

The output is something like:

{
id: 1
name: Andrew
address: home
photo: {
          id: 2
          photo: image1
       }
credit: {
          [
              {
              id: 6
              credit_status: foo,
              id: 2
              credit_status: bar
              }
          ]
        }
},
{
id: 2
name: Mark
address: home
photo: {
          id: 5
          photo: image4
       }
credit: {
          [
              {
              id: 10
              credit_status: foo,
              id: 6
              credit_status: bar,
              id: 8
              credit_status: bar
              }
          ]
        }
}

I want to filter the credit in with('credit') also. My desired output:

{
id: 1
name: Andrew
address: home
photo: {
          id: 2
          photo: image1
       }
credit: {
          [
              {
              id: 2
              credit_status: bar
              }
          ]
        }
},
{
id: 2
name: Mark
address: home
photo: {
          id: 5
          photo: image4
       }
credit: {
          [
              {
              id: 6
              credit_status: bar,
              id: 8
              credit_status: bar
              }
          ]
        }
}

You can just do the same filtering on the with (constraining eager loading):

$creditFilter = function ($q) use ($status) {
    $q->where('credit_status', $status);
};

Player::with(['photo', 'credit' => $creditFilter])
    ->whereHas('credit', $creditFilter)
    ->paginate(15);

You can save that closure and pass it to the with and whereHas so you don't have to type the same identical closure twice.

Laravel 5.6 Docs - Eloquent - Relationships - Eager Loading - Constraining Eager Loads

  • 1
Reply Report