Laravel Eloquent: eager loading of multiple nested relationships
Asked Answered
I

5

84

What laravel says:

$books = App\Book::with('author.contacts')->get();

What I need is something like this

$books = App\Book::with('author[contacts,publishers]')->get();

where we eager load multiple relationships within a relationship.

Is this possible?

Inwardness answered 18/2, 2016 at 19:30 Comment(0)
S
157

You can do

 $books = App\Book::with('author.contacts','author.publishers')->get();
Shuttlecock answered 18/2, 2016 at 19:46 Comment(6)
just to add, it will fetch the corresponding author data as well ofcourse.Osswald
Follow-up: I have a much more complex model and want to return a single collection, but like the original poster, wish I could use multiple nested relationships at a lower child level like $event = event::with(['streams.experiences.selectors.['digitalprops.frames','filters']','streams.datacaptures'])->find($eventcode);Declarer
@Declarer How do you execute this code in Laravel? $event = event::with(['streams.experiences.selectors.['digitalprops.frames','filters']','streams.datacaptures'])->find($eventcode);. It shouldn't work...!Intricate
Right @Intricate -- I said I WISH I could... sorry for the confusion.Declarer
does author is table name or what?Butterwort
@msbomrel, author is a relationship method in the Book classContracture
C
51

Laravel documentation on eager loading recommends listing the relationships in an array as follows:

$books = App\Book::with(['author.contacts', 'author.publishers'])->get();

You can have as many relationships as desired. You can also specify which columns should be included for a relationship like this:

//only id, name and email will be returned for author
//id must always be included
$books = App\Book::with(['author: id, name, email', 'author.contacts', 'author.publishers'])->get();

You may also add constrains as follows:

$books = App\Book::with(['author: id, name, email', 'author.contacts' => function ($query) {
                                          $query->where('address', 'like', '%city%');
                                     }, 'author.publishers'])->get();
Contracture answered 8/11, 2018 at 10:17 Comment(3)
This is the best overview how to eager load efficiently!Neuron
This looks amazing! Thanks for your input!Stantonstanway
Honestly! This is WAY better than Laravel's documentation.Mayda
O
12

So, now you can try

$books = App\Book::with(['author' => function($author){
     $author->with(['contacts', 'publishers'])->get();
}])->get();
Odoric answered 14/2, 2021 at 4:28 Comment(1)
I think that ->get() is not needed at all within the closureParker
C
5

From Laravel 9, the neatest way is the nested array :

$books = App\Book::with(['author' => [
             'contacts',
             'publishers'
         ])->get();

Reference

Cultivate answered 3/10, 2022 at 18:39 Comment(0)
O
1

When eager load nested relationships and we want to select just some columns and not all using relationship:id,name, always include the foreign key to the nested models, else they won't load at all.

Fort example, we have orders that have identities that have addresses.

This will not load the address:

User::orders()
    ->with('identity:id,name', 'identity.address:id,street')

This will load the address because we have supplied the address_id foreign key:

User::orders()
    ->with('identity:id,address_id,name', 'identity.address:id,street')
Obed answered 8/11, 2021 at 9:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.