簡體   English   中英

如何在Doctrine2中的單個查詢中加載結果集的所有關聯

[英]How to load all associations for a result set in a single query in Doctrine2

我有一些漂亮的基本實體,其中包含故事和標簽,我試圖盡可能高效地加載它們。

當我查詢這樣的故事時:

SELECT a FROM Foo\Article a WHERE a.id IN (1,2,3,4,5)

我看到正在運行以下SQL查詢:

SELECT f0_.id AS id_0, f0_.title AS title_1 FROM foo_article f0_ WHERE f0_.id IN (1, 2, 3)
SELECT t0.name AS name_1, t0.article_id AS article_id_2 FROM foo_tag t0 WHERE t0.article_id = 1
SELECT t0.name AS name_1, t0.article_id AS article_id_2 FROM foo_tag t0 WHERE t0.article_id = 2
SELECT t0.name AS name_1, t0.article_id AS article_id_2 FROM foo_tag t0 WHERE t0.article_id = 3

我想看到的地方:

SELECT f0_.id AS id_0, f0_.title AS title_1 FROM foo_article f0_ WHERE f0_.id IN (1, 2, 3)
SELECT t0.name AS name_1, t0.article_id AS article_id_2 FROM foo_tag t0 WHERE t0.article_id IN (1, 2, 3);

源代碼看起來像這樣。 實際代碼的縮寫。

<?php
namespace Foo;

use Doctrine\ORM\Mapping as ORM;

/**
 * Class Tag
 *
 * @ORM\Entity()
 * @ORM\Table(name="foo_tag")
 *
 * @package Foo
 */
class Tag {

    /**
     * @ORM\Column(type="string")
     * @ORM\Id()
     */
    protected $name;

    /**
     * @ORM\ManyToOne(targetEntity="\Foo\Article",cascade={"persist"},fetch="LAZY",inversedBy="tags")
     * @ORM\Id()
     */
    protected $article;
}

/**
 * Class Article
 *
 * @ORM\Entity()
 * @ORM\Table(name="foo_article")
 *
 * @package Foo
 */
class Article {

    /**
     * @ORM\Id @ORM\Column(type="integer", name="id") @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $title;

    /**
     * @ORM\OneToMany(targetEntity="\Foo\Tag",mappedBy="article",cascade={"persist"},fetch="EAGER")
     */
    protected $tags;

}

我在想自己的一種可能方法是在存儲庫類中添加類似的內容。 但這還不是很正確。 我想要一種對其他關聯更可移植的東西,在每次查詢實體時都可以使用,並且還可以用於分頁查詢。

可能是類似postLoad的事件中的某個事件,它覆蓋了整個結果集(而不是每個實體的postLoad)。

$qb = $entityManager->getRepository('Foo\Article')->createQueryBuilder('a')
    ->where('a.id IN (1,2,3)');

$list = $qb->getQuery()->execute();

/** @var Foo\Article[] $indexed */
$indexed = array_reduce($list, function($result, \Foo\Article $article) {
    $result[$article->getId()] = $article;
    return $result;
}, Array());

$tags = $entityManager->getRepository('Foo\Tag')->createQueryBuilder('t')
    ->where('t.article IN (:ids)')
    ->setParameter('ids', $indexed)
    ->getQuery()->execute();

array_map(function(\Foo\Tag $tag) use ($indexed) {

    /** @var \Doctrine\ORM\PersistentCollection $collection */
    $collection = $tag->getArticle()->getTags();
    $collection->add($tag);
    $collection->setInitialized(true);

}, $tags);

foreach($indexed as $article) {
    $article->getTags()->takeSnapshot();
    $article->getTags()->setInitialized(true);
}

/** @var Foo\Article $article */
// and now use the Articles and Tags, to make sure that everything is loaded
foreach($list as $article) {
    $tags = $article->getTags();
    print " - ".$article->getTitle()."\n";
    foreach($tags as $tag) {
        print "   - ".$tag."\n";
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM