类别[
id
,parent
,children
,left
,right
,level
,{{ 1}},root
]产品[
products
,id
,category
]MarketSegment [
marketSegments
]此外,每个实体都有
id
,name
,description
等字段但那些与我的问题无关。
图例:
slug
- 类别,c
- 产品
标有*的产品标有细分市场“Export to USA”
p
对于给定数据和 $ category = 食品, $ marketSegment = 导出到美国预期结果将是:
Food [c, id: 1, level: 0]
---> Vegetables [c, id: 2, level: 1]
--------------> Potato [p, id: 1]
--------------> Carrot [p, id: 2]
---> Fruits [c, id: 3, level: 1]
--------------> Berries [c, id: 5, level: 2]
---------------------------> Grapes [p, id: 3]
--------------> Hesperidiums [c, id: 6, level: 2]
---------------------------> Orange* [p, id: 4]
---> Meat [c, id: 4, level: 1]
--------------> Beef* [p, id: 5]
为什么?
$filteredCategories = [Fruits, Meat]
因为它包含标有导出到美国的产品Meat
Beef
因为它包含类别Fruits
,其中包含标记产品。嵌套树中包含标记产品的类别的深度无关紧要。
此:
Hesperidiums
对于 $ category = 体育应该返回:[Sports [c]
-----> Individual [c]
----------------> Fight [c]
----------------------> MMA [c]
--------------------------> Boxing gloves* [p]
]。
对于 $ category = 战斗应返回:[Individual
]。
MMA
答案 0 :(得分:3)
NestedTreeRepository
有一个方法getChildrenQueryBuilder()
,允许您查询给定父节点的子节点,并且有一个参数用于查询多个深层的节点层次结构。您应该调查NestedTreeRepository
附带的方法和选项,以便不需要手动构建DQL。
我不完全确定您的所有代码是如何设置的,因此我无法提供准确的解决方案,但我认为您可以解决这个问题:)
NestedSet文档:http://www.gediminasm.org/article/tree-nestedset-behavior-extension-for-doctrine-2
答案 1 :(得分:1)
谢谢约翰!使用NestedTreeRepository我找到了解决方案:
我为Category类创建了自己的Repository,它扩展了NestedTreeRepository并创建了一个自定义方法
public function findSubcategoriesFilteredByMarketSegment(Category $ parentNode,MarketSegment $ segment)
{
// get DIRECT CHILDREN for $parentNode $qb = $this->getChildrenQueryBuilder($parentNode, true); $qb->leftJoin($qb->getRootAlias().'.products', 'prod') ->leftJoin('prod.marketSegments', 'seg'); // subquery -> get all children (direct and indirect) // for DIRECT CHILD from main query $sqb = $this->_em->getRepository('AvocodeCatalogBundle:Category')->createQueryBuilder('sub'); // join products and market segments $sqb->leftJoin($sqb->getRootAlias().'.products', 'sub_prod') ->leftJoin('sub_prod.marketSegments', 'sub_seg'); // to match children of main query's DIRECT CHILD // they need to have left and right values between DIRECT CHILD's left and right $sqb->where( $sqb->expr()->andX( $sqb->expr()->gt('sub.lft', $qb->getRootAlias().'.lft'), $sqb->expr()->lt('sub.rgt', $qb->getRootAlias().'.rgt'), $sqb->expr()->eq('sub.root', $qb->getRootAlias().'.root') )); // match only children with products related to $segment $sqb->andWhere($sqb->expr()->eq('sub_seg.id', ':segment_id')); // BACK TO MAIN QUERY // select only parentNode children THAT $qb->andWhere( $qb->expr()->orX( // contain product with related segment $qb->expr()->eq('seg.id', ':segment_id'), // or // have a child (direct or indirect) that does contain such product $qb->expr()->exists($sqb->getDQL()) )) ->setParameter('segment_id', $segment->getId()); return $qb->getQuery()->getResult();
}