Laravel Eloquent:减少查询次数

Noo*_*der 1 php mysql laravel eloquent

假设我在users桌面上有250个用户,每个用户都有一本或多本书,每本书都有一个或多个章节.现在我想打印用户名和他们的书名.

控制器:

$users = User::all();
Run Code Online (Sandbox Code Playgroud)

在刀片中:

@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
Run Code Online (Sandbox Code Playgroud)

现在要克服n + 1问题,查询应该是

$users = User::with('books')->get();
Run Code Online (Sandbox Code Playgroud)

现在查询数量仅为2.

我想打印带有章节数的书名,如this-> 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
Run Code Online (Sandbox Code Playgroud)

因此,对于包含1500章的750本书,查询数约为752,如果章节数增加则增加.

有没有更好的Eloquent方法来减少它或我应该去原始的SQL查询?

Ale*_*nin 10

您不需要加载所有章节数据,然后手动计算每个集合。使用withCount()来代替:

$users = User::with('books')->withCount('chapters')->get();
Run Code Online (Sandbox Code Playgroud)

如果您想计算关系中的结果数量而不实际加载它们,您可以使用 withCount 方法,它将在您的结果模型上放置一个 {relation}_count 列。

  • 这可能是一个更有效的答案,因为每个章节对象都没有被加载到内存中。赞成。 (2认同)

mai*_*o84 5

来自Eloquent文档:

嵌套的渴望加载

要急切加载嵌套关系,您可以使用"dot"语法.例如,让我们在一个Eloquent声明中急切地加载本书的所有作者和作者的所有个人联系人:

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

在您的情况下,您可以使用以下内容检索所需的嵌套关系:

User::with('books.chapters')->get();
Run Code Online (Sandbox Code Playgroud)