Reputation: 2896
Let's say I have 250 users in users
table and each user has one or many books, and each book has one or many chapters. Now I would like to print the user names, with their book names.
Controller:
$users = User::all();
in blade:
@foreach($users as $user)
<tr>
<td>{{ $user->id }}</td>
<td>{{ $user->name }}</td>
<td>
@foreach($user->books as $book)
{{ $book->name }},
@endforeach
</td>
</tr>
@endforeach
# of queries 252
Now to overcome the n+1 problem, the query should be
$users = User::with('books')->get();
Now the # of queries are only 2.
I want to print the book names with number of chapters like this-> BookName(# of chapters). So in my blade
@foreach($users as $user)
<tr>
<td>{{ $user->id }}</td>
<td>{{ $user->name }}</td>
<td>
@foreach($user->books as $book)
{{ $book->name }} ({{ $book->chapters->count() }}),
@endforeach
</td>
</tr>
@endforeach
so for 750 books with 1500 chapters the # of queries are about 752 and it increases if chapter number increases.
Is there any better Eloquent way to reduce it or should I go for raw SQL queries?
Upvotes: 1
Views: 4973
Reputation: 163788
You don't need to load all chapters data and then manually count each collection. Use withCount()
instead:
$users = User::with('books')->withCount('chapters')->get();
If you want to count the number of results from a relationship without actually loading them you may use the withCount method, which will place a {relation}_count column on your resulting models.
Upvotes: 10
Reputation: 11951
From the Eloquent Documentation:
Nested Eager Loading
To eager load nested relationships, you may use "dot" syntax. For example, let's eager load all of the book's authors and all of the author's personal contacts in one Eloquent statement:
$books = App\Book::with('author.contacts')->get();
In your case, you can retrieve the nested relationships you need with the following:
User::with('books.chapters')->get();
Upvotes: 6