2

我有一种OneToMany关系,一支足球队有很多球员。我想列出所有足球队并显示每支球队队长的名字。

每个玩家实体都有一个外键(team_id)和一个设置为 0 或 1 的字段“队长”。我目前正在运行以下查询:

 $teams = $this
             ->getDoctrine()
             ->getRepository('FootballWebsiteBundle:Team')
              ->createQueryBuilder('t')
             ->setFirstResult(($pageNumber * $resultPerPage) - $resultPerPage)
             ->setMaxResults($resultPerPage)
             ->add('where','t.deleted = 0')
             ->add('orderBy', 't.name DESC')
             ->getQuery()->getResult();

然后,当我遍历树枝中的每个团队时,我运行 team.getTeamCaptain().getName() ,这是我的团队实体中的一个过滤器:

public function getTeamCaptain() {
    $them  = $this->players->filter(function($p) {
        return $p->getCaptain() == 1;
    });

    return $them->first();
}

有没有更好的方法来运行这个查询?

4

1 回答 1

4

首先,您可能希望获取并加入每个检索到的球队的球员,以避免在模板渲染期间延迟加载他们。这是 DQL:

SELECT
    t, p
FROM
    FootballWebsiteBundle:Team t
LEFT JOIN
    t.players p
WHERE
    t.deleted = 0
ORDER BY
    t.name DESC

可以使用以下查询构建器 API 调用来构建:

 $teamsQuery = $this
         ->getDoctrine()
         ->getRepository('FootballWebsiteBundle:Team')
         ->createQueryBuilder('t')
         ->addSelect('p')
         ->leftJoin('t.players', 'p')
         ->add('where','t.deleted = 0')
         ->add('orderBy', 't.name DESC')
         ->getQuery()

然后将此查询包装到一个Paginator对象中(因为在 fetch-joiningsetMaxResultssetFirstResult 不能信任):

$paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($teamsQuery, true);

$teamsQuery
     ->setFirstResult(($pageNumber * $resultPerPage) - $resultPerPage)
     ->setMaxResults($resultPerPage)

在您看来,您可以像下面的伪代码一样迭代团队:

foreach ($paginator as $team) {
    echo $team->getTeamCaptain() . "\n";
}

您还可以getTeamCaptain通过使用SelectableAPI在您的方法中获得一些额外的性能:

public function getTeamCaptain() {
    $criteria = new \Doctrine\Common\Collections\Criteria();

    $criteria->andWhere($criteria->expr()->eq('captain', 1));

    return $this->players->matching($criteria)->first();
}

这里的优势主要在关联players尚未初始化时相关,因为这将避免完全加载它。情况并非如此,但我认为这是一种很好的做法(而不是重新发明集合过滤逻辑)。

于 2013-02-14T00:31:39.367 回答