我们说users
表中有250个用户,每个用户都有一本或多本书,每本书都有一个或多个章节。现在我想打印用户名和他们的书名。
控制器:
$users = User::all();
刀片中的:
@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
现在要克服n + 1问题,查询应该是
$users = User::with('books')->get();
现在查询数量只有2个。
我想用这样的章节打印书名 - &gt; BookName(章节数)。所以在我的刀片中
@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
因此,对于包含1500章的750本书,查询数量约为752,如果章节数增加则会增加。
有没有更好的Eloquent方法来减少它,还是应该进行原始SQL查询?
答案 0 :(得分:5)
From the Eloquent Documentation:
嵌套预先加载
要急切加载嵌套关系,您可以使用“dot”语法。例如,让我们在一个Eloquent声明中急切地加载本书的所有作者和作者的所有个人联系人:
$books = App\Book::with('author.contacts')->get();
在您的情况下,您可以使用以下内容检索所需的嵌套关系:
User::with('books.chapters')->get();
答案 1 :(得分:4)
您不需要加载所有章节数据,然后手动计算每个集合。请改用withCount()
:
$users = User::with('books')->withCount('chapters')->get();
如果您想要计算关系中的结果数而不实际加载它们,您可以使用withCount方法,该方法会在结果模型上放置{relation} _count列。