2

I have read several posts on why eager loading uses multiple queries rather than joining here, here, and here. However, I have a situation that I think warrants using a join instead of eager loading. How would I construct the query so that I can access the sub-object as if it were a normally eager loaded object?

Example: Getting people that live on a certain street, and loading that address at the same time. I don't want to load all the person's addresses, incase he lives at many places; just the places that match the query. With eager loading and whereHas I have to duplicate the query, and it's not always this simple of a query:

People::with(['address', function($query) use ($street_name){
  return $query->where('street_name', $street_name);
}])->whereHas('address', function($query) use ($street_name){
  return $query->where('street_name', $street_name);
})->get();

could be

People::query()->join('address', function($join){
  $join->on(...)
})->where('street_name', $street_name);

The problem then is that I cannot use this:

$person->address

Is there a way to take the join and massage it (using selects?) so that it appears like it was eager loaded?

Community
  • 1
  • 1
whiterook6
  • 3,270
  • 3
  • 34
  • 77
  • These 2 queries will return different results. You want to use eloquent relationships here if a person can have more than 1 address or join if person can have 1 address only (that match this query). [Here](http://laravel.io/forum/11-03-2014-withwherehas#reply-16483) is a decent (ish) workaround for your problem with relationships. – DevK Jan 20 '17 at 20:20
  • If you do a join you can't do `$person->address->address_attribute` but you can do directly `$person->address_attribute`. Joined table's attributes will be attached to the `$person`. – DevK Jan 20 '17 at 20:28

1 Answers1

5

You could do the following:

People::join('addresses', 'addresses.people_id', '=', 'people.id')
->selectRaw('people.*')
->where('street_name', $street_name)
->with('addresses')
->get();

This uses a join and eager loading.

With the join alone, you can access the following though:

$person->street_address
Kyle
  • 405
  • 2
  • 6
  • Ideally I would have it go into an object so I can still access it like this: $person->address->street_address, but I suppose I could write some sort of attribute getter to see if the address is loaded or not. – whiterook6 Feb 23 '17 at 23:14