我正在测试 API 平台,我遇到了 n+1 个 Doctrine 问题。我有一个名为 Car 的实体,它与 Driver 具有 ManyToMany 关系。我没有做任何定制,我只是在默认(显然)状态下测试 API 平台。
汽车实体:
#[ORM\ManyToMany(targetEntity: Driver::class, mappedBy: 'car', fetch: 'EAGER')]
#[ORM\JoinTable(name: "cars_to_drivers")]
private Collection $drivers;
驱动实体:
#[ORM\ManyToMany(targetEntity: Car::class, mappedBy: 'driver', fetch: 'EAGER')]
#[ORM\JoinTable(name: "cars_to_drivers")]
private Collection $cars;
当我点击 GET 端点获取汽车(每页 30 辆)时,我可以在 Doctrine 分析器中看到正在运行 32 个查询:一个用于获取计数,一个用于获取所有汽车,以及每辆车一个查询为那辆车找司机尽管我强迫急切加载,但 Doctrine 似乎坚持要进行这些额外的查询。我该如何解决这个问题?
您无需恢复到原始 sql 即可完成 N+1 解决方案。正如 Cerad 所建议的那样,您需要进行自定义查询,但他并不是指 SQL。这可以在 DQL 中或使用 QueryBuilder 完成。
这是最简单的例子。这将消除在选择具有相关驱动程序的汽车时的 N+1 问题。
// CarRepository.php
public function getCars()
{
return $this->createQueryBuilder('car')
->innerJoin('car.drivers', 'drivers')
->addSelect('drivers');
->getQuery()
->getResult();
}
// ...
然后您使用
getCars
查询而不是您当前使用的任何查询。当然你可以过滤或限制查询(用于分页)。