当我们不查询时,在主页的调试栏可以看到有多个查询,实际上是你分类数+1个查询,从代码里可以看到对每一个分类都进行了一次查询 其实这是因为我们在控制器里进行了一次Category的查询,然后在twig中又进行了一次循环,然后使用了 ({{ category.fortuneCookies|length }})对分类下的数据进行查询,所以产生了n+1次查询。
针对这种情况,我们可以使用JOIN来修复,
public function findAllOrdered(): array
{
$qb
= $this->createQueryBuilder('category')
->addSelect('fortuneCookie')
->leftJoin('category.fortuneCookies', 'fortuneCookie')
->addOrderBy('category.name', Criteria::DESC);
$query = $qb->getQuery();
return $query->getResult();
}
然后刷新,现在我们只有一次查询了,当我们->createQueryBuilder('category')时,查询会把Category数据查出来,然后我们->leftJoin并->addSelect时,查询会添加fortuneCookie的数据, 但并不会改变方法返回的内容,只不过我们调用fortuneCookies时它会意识到它已经拥有该数据,因此它不会进行查询,而是使用它。
真正重要的是,当我们使用 ->addSelect() 从 JOIN 获取数据时,它不会改变我们的方法返回的内容。不过稍后,我们会看到使用 select() 或 addSelect() 确实会改变我们的查询返回的内容。
所以我们只使用JOIN就把查询减少到1个,但是因为我们只计算每一个fortuneCookies的数量,所以还有另一个解决方案。接下来我们来谈谈EXTRA_LAZY关系。