学说,如何连接多对多关系的表

时间:2017-07-31 10:16:08

标签: php symfony doctrine query-builder

我正在使用Symfony 2,Doctrine和Query Builder。 我有2个表:产品和类别。

产品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"将产品与产品联系起来。 我没有关于我的类别ORM文件中的产品的信息。

我尝试使用QueryBuilder构建查询,但我不了解如何开始对类别表进行查询,该类表链接产品以便在产品上添加一些过滤器。

$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 ...

有人能帮助我吗?谢谢。

2 个答案:

答案 0 :(得分:1)

当你使用ManyToMany时,在关系管理的背景下为你做了很多“魔术”,所以你可以做快速连接,而不需要考虑连接的笛卡尔积

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

或快速冲洗,如

$product->setCategories($categories);
$em->persist($product);
$em->flush();

缺点是,为了使教义能够做到这种“魔术”,您无法访问需要进行所需联接的内部联接表。

如果你没有在'category'上定义反向关系,我也不认为doctrine可以为你管理这个join。但请注意,如果您有许多产品,这样做会占用很大的内存,因为学说会延迟加载您所有类别的所有产品。

如果您不想定义反向关系(由于上述问题),解决方法是在关系表上定义实体(类似于ProductCategory),并定义2 1-> 1这个实体的2列上的关系。然后,只要您想从Category开始创建查询构建器并与Product连接,就可以将此实体用作桥接,而无需在Category

上定义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:尝试使用上面示例中的短别名,以避免任何“文字”异常。

希望这有帮助,

Alexandru Cosoi

答案 1 :(得分:0)

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

$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提供的有用信息!