我有一个包含两个JOIN的表:广告,技能和每行的级别:
我可以通过以下方式获取数据:
$listAdvertSkills = $em
->getRepository('OCPlatformBundle:AdvertSkill')
->findBy(array('advert' => $advert))
;
如何加入"加入"方法?像这样的东西?
public function getSkillsForThisAdvert($id){
$qb = $this
->createQueryBuilder('a')
->join('a.advert', 'adv')
->where('adv.id', $id) //addSelect here?
->join('a.skill', 'sk');
->addSelect('sk');
return $qb->getQuery()->getResult();
}
另外,如果是"类别"的数组在每个广告中,如果我想得到:
所有类别,
所有来自一个类别的广告,
一个广告和关卡所需的所有技能,
请求是什么?
并在另一页,同样但来自技巧:
所有技能,
所有具有这些技能的广告,
来自一个广告的所有类别。
只是要了解正确的方法,它不适用于任何工作。
由于
答案 0 :(得分:1)
您是对的 - 第一种方法可行,但如果您想从任何关联实体检索数据,则会运行其他查询。如果列出大量行,则可能会导致数十个其他查询,因此使用JOIN并预先选择其他实体是一种很好的做法。
有关进一步说明 - 如果您在查询构建器中加入广告和技能表而不执行任何其他操作,则SQL查询将加入表,但不会从中选择任何信息。因此,如果您稍后尝试访问它们,则Doctrine必须调用更多SQL查询才能检索该信息。这就是addSelect
电话很重要的原因。那些告诉Doctrine(和SQL)检索关联实体的所有信息。例如,如果广告有5种额外技能,那么您的SQL将返回5行,但是Doctrine会将其水合成5个技能实体的数组(或Doctrine ArrayCollection),这些实体可以从单个Advert对象访问返回。
您的QueryBuilder可能如下所示:
public function getSkillsForThisAdvert($id)
{
$qb = $this
->createQueryBuilder('a')
->addSelect('adv')
->addSelect('sk')
->join('a.advert', 'adv')
->join('a.skill', 'sk');
->where('a.id = :identifier')
->setParameter(':identifier', $id);
return $qb->getQuery()->getResult();
}
您也可以将Advert
对象作为$advert
传递给您的函数,并将查询构建器调用更改为->where('a = :advert')->setParameter('advert', $advert);
我可能还建议将函数名称更改为getSkills
,因为您已经传递了所需的广告对象。
如果您不喜欢使用QueryBuilder,您只需使用看起来更像SQL的DQL Queries(而不是先使用QueryBuilder构建,然后使用getQuery
检索查询)。只要您的实体与其相应的关联实体正确定义,Doctrine将为您完成大部分繁重工作。如果你想选择一个广告及其所有相关技能,Doctrine已经为你做了一个工作,你可以为数组或ArrayCollection中的相应技能对象检索一个对象,而不是一个返回多行的原始SQL语句。重复,并要求你自己处理。
您还可以执行以下操作,而不是多个addSelect
语句:
->select(array('a', 'adv', 'sk'))
此外,如果您要有多个WHERE条件,请将where
更改为addWhere
- 实际上,最好始终使用addWhere
。