Doctrine,如何连接具有多对多关系的表

Doctrine, how to join tables with many to many relation

我正在使用 Symfony 2、Doctrine 和 Query Builder。 我有 2 tables:产品和类别。

产品 ORM 文件包含以下内容:

manyToMany:
    categories:
        targetEntity: Pim\Component\Catalog\Model\CategoryInterface
        joinTable:
            name: pim_catalog_category_product
            joinColumns:
                product_id:
                    referencedColumnName: id
                    onDelete: CASCADE
            inverseJoinColumns:
                category_id:
                    referencedColumnName: id
                    onDelete: CASCADE

这样做的效果是,我有一个名为 "pim_catalog_category_product" 的 table 链接类别和产品。 我的类别 ORM 文件中没有关于产品的信息。

我正在尝试使用 QueryBuilder 构建查询,但我不明白如何从类别 table 的查询开始,该类别链接产品以便在产品上添加一些过滤器。

$qb = $this->getEntityManager()
        ->createQueryBuilder()
        ->addSelect('category')
        ->from($this->_entityName, 'category')
        ->join('Pim\Component\Catalog\Model\Product', 'product', 'WITH', 'category.id IN (product.categories);

但现在我收到以下错误:

Expected Literal, got 'product' at ... SELECT category FROM Pim\Bundle\CatalogBundle\Entity\Category category INNER JOIN Pim\Component\Catalog\Model\Product product WITH category.id IN (product.categories) at ...

有人可以帮助我吗?谢谢。

当你使用 ManyToMany 学说时,在后台为你做了很多关于关系管理的事情 'magic',这样你就可以进行快速连接,而无需考虑连接的笛卡尔积

$this->getEntityManager()
        ->createQueryBuilder()
        ->addSelect('product')
        ->from($this->_entityName, 'p')
        ->join('p.category')

或像

这样的快速冲洗
$product->setCategories($categories);
$em->persist($product);
$em->flush();

缺点是,为了让 doctrine 能够做到这一点 'magic' 您无权访问内部联接 table 您需要执行所需的联接.

此外,如果您不在 'category' 上定义反向关系,我认为学说无法为您管理此连接。但请注意,如果您有很多产品,这样做会产生很大的内存开销,因为 doctrine 会延迟加载您类别中的所有产品。

如果您不想定义反向关系(由于上述问题),解决方法是在您的关系 table 上定义一个实体(类似于 ProductCategory),然后定义2 此实体的 2 列上的 1->1 关系。然后,只要您想创建从类别开始并加入产品的查询构建器,就可以使用此实体作为桥梁,而无需在类别

上定义 M<->M 关系

类似于

$qb = $this->getEntityManager()
    ->createQueryBuilder()
    ->addSelect('c')
    ->from($this->_entityName, 'c')
    ->join('Pim\Component\Catalog\Model\ProductCategory', 'pc', 'WITH', 'c.id = pc.category_id')
    ->join('Pim\Component\Catalog\Model\Product', 'p', 'WITH', 'p.id = pc.product_id')

PS:尝试像上面的例子一样使用短别名,以避免更多的 "literal" 异常。

希望对您有所帮助,

亚历山德鲁·科索伊

我终于设法通过子查询和从 ManyToMany 关系加入 table 的正确方法解决了我的问题。

$qb2 = $this->getEntityManager()
            ->createQueryBuilder()
            ->addSelect('product_category.id')
            ->from('Pim\Component\Catalog\Model\Product', 'product')
            ->join('product.categories', 'product_category');

在我的主要查询中:

$qb->andWhere($qb->expr()->in('category.id', $qb2->getDQL()));

感谢 Alexandru Cosoi 和 Stmm 提供的有用信息!