如何在仍然渴望加载所有实体的同时在@ManyToMany上指定条件?

时间:2015-09-15 22:52:08

标签: doctrine-orm

我有一个Restaurant实体,可以有很多Cuisines(意大利语,寿司等):

/**
 * @ORM\Entity
 */
class Restaurant
{
    /**
     * @ORM\ManyToMany(targetEntity="Cuisine")
     */
    protected $cuisines;
}

当我加载餐馆列表时,我想急切地加载它的菜肴,以避免在每家餐厅调用getCuisines()时往返数据库。使用DQL:

SELECT r, c
FROM Model\Restaurant r
LEFT JOIN r.cuisines c

一切都很好。

现在如果我想要归还所有包含特定美食的餐馆,我可以使用这个DQL:

SELECT r
FROM Model\Restaurant r
LEFT JOIN r.cuisines c
WHERE c.id IN (?)

那也很好。现在,如果我想同时做两件事:

SELECT r, c
FROM Model\Restaurant r
LEFT JOIN r.cuisines c
WHERE c.id IN (?)

餐馆列表是正确的,但他们的$cuisines只会填充ID与给定列表匹配的餐馆。这完全打破了模式。

我如何通过美食限制退回的餐厅,同时仍然渴望加载完整的美食列表?

3 个答案:

答案 0 :(得分:0)

如果你不介意总是急切负担美食:

/**
 * @ManyToMany(targetEntity="Cuisine", fetch="EAGER")
 */

否则......很难。如果是OneToMany,您可以暂时更改该查询:http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html#temporarily-change-fetch-mode-in-dql

但是使用ManyToMany,您无法在每个查询的基础上执行此操作。

答案 1 :(得分:0)

也许我错了,但通常你应该能够获得整个ArrayCollection而不在查询中指定它。

$qb = $em->createQueryBuilder();
$qb->select('r')
   ->from('Model\Restaurant', 'r')
   ->leftJoin('r.cuisines', 'c')
   ->where('c.id IN ?1')
   ->setParameter(1, $ids);
$query = $qb->getQuery();
$result = $query->getResult();

foreach ($result as $restaurant){
    //contains the whole arrayCollection
    var_dump($restaurant->getCuisines());
}

在您的餐厅实体中确保有一个构造函数。

public function __construct() {
    $this->cuisines = new ArrayCollection();
}

答案 2 :(得分:0)

在您当前的查询中,您通过Cuisines模型的属性限制结果集 - 因此您无法获得您尝试获取的餐馆的所有关系。尝试使用如下的子选择:

SELECT r, c
FROM Model\Restaurant r
LEFT JOIN r.cuisines c
WHERE r.id IN (
    SELECT DISTINCT sr.id 
    FROM Model\Restaurant sr
    LEFT JOIN sr.cuisines sc 
    WHERE sc.id IN (?)
)

说明:子选择执行您在上面开发的同一查询,以同时获取两者。但是,我们只返回符合标准的餐馆ID。然后,在主要选择中,我们用所有他们的菜肴来获取所有这些餐馆。