我正在尝试优化查询,因为我需要一个简单的列表作为一个附属于多个实体的实体。 所以我创建了这个查询,你应该只给我一个id和名字:
public function findAllOrderByName() {
$qb = $this->createQueryBuilder('a');
$query = $qb->select(array('partial a.{id,name}'))
->addOrderBy('a.name', 'ASC')
->getQuery();
return $query->getResult();
}
在控制器中返回它:
public function getInstrumentsAction()
{
$instruments = $this->getDoctrine()->getRepository('AcmeInstrumentBundle:Instrument')->findAllOrderByName();
return array('instruments' => $instruments);
}
而不是仅仅让我回到两个阵营,给我完整的对象,从而包括其他相关实体的所有领域。
为什么不起作用?
答案 0 :(得分:5)
它实际上完全按照设计工作。您所观察到的是您的相关实体的延迟加载。
首先添加:
echo $query->getSQL() . "\n";
return $query->getResult();
你会看到类似的东西:
SELECT p0_.id AS id0, p0_.name AS name1 FROM instrument p0_ ORDER BY p0_.name ASC
因此,只有您要求实际查询的两个字段。
echo sprintf("Instrument %s %s %s\n",
$instrument->getName(),$instrument->getSomeotherScalervalue());
你会看到,当名字被回显时,其他一些值甚至不在仪器表中。
就关系而言,让我们假设乐器与人之间有一种关系。
$persons = $instrument->getPersons();
你会期望$ people是一个空数组,但它实际上是一个相当聪明的Doctrine \ ORM \ PersistentCollection。一旦你尝试用$ person做任何其他事情(即使是像count($ persons)那样简单的事情,也会触发另一个查询,并且所有链接的人物对象都会被加载。
这就是你所看到的。您实际上可以在logs / dev.log中查看查询。只要您拉入仪器,就只会生成一个查询。一旦你尝试用关系做某事,另一个查询就会消失。
解决方法
不要试图访问关系。
在访问关系之前,您可以执行$ persons-> setInitialized(true);这将阻止加载。显然有点痛苦。
由于优化是您的目标,因此只返回一个数组结果。根本没有任何对象。
您也可以继续在查询中加入您的关系,但使用partial来引入相关实体的ID。您的查询工作有点困难,但您不必担心会触发其他查询。
如果有一些方法可以在特定查询的基础上阻止延迟加载,那将会很好。但是,如果有,我一直无法找到它。