2

OneToMany1つのサッカーチームに多くの選手がいるという関係があります。すべてのサッカーチームを一覧表示し、各チームのキャプテンの名前を表示したいと思います。

各プレーヤーエンティティには、外部キー(team_id)と、0または1に設定されたフィールド'captain'があります。現在、次のクエリを実行しています。

 $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次に、このクエリをオブジェクトにラップします (setMaxResultssetFirstResult は fetch-joining では信頼できないため):

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

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

ビューでは、次の擬似コードのようにチームを反復できます。

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

APIgetTeamCaptainを使用して、メソッドのパフォーマンスをさらに向上させることもできます。Selectable

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 に答える