2011-10-11 48 views
1

我目前正在学习symfony1.4,并且试图以有限的成功导航教条的嵌套集合特性。我有一个类别表使用多树的嵌套集行为。我的类别树数据可多达六个深...symfony1.4嵌套设置通过级别的导航

Categories: 
    columns: 
    category_name: 
     type: string(40) 
    actAs: 
    NestedSet: 
     hasManyRoots: true 
     rootColumnName: parent_id 

这些类别的产品,我想一个网页通过类别进行过滤,以显示到达叶是类产品如显示根,如果选择了一个根,然后显示它的子项,那么如果选择了一个子项,则显示它的子项等,直到你选择一个叶子节点。 here's an image which may describe it better

我试图构建过滤类别的2维数组,以传递给视图...没有成功。任何解决方案将有助于我的头炸!

非常感谢,

抢。

回答

5

改写

的改写你的问题:你需要和他们的兄弟姐妹(您的节点与节点的每一个祖先)。

其他的改写:你需要你的节点的所有祖先的所有孩子的(但不是所有他们的后代)

沿着而且,不要以为你应该设置为true hasManyRoots,除非你有几家商店。现在让我们假设你有一个根,你可以命名为'shop'

这是第三个更简单的改写:所有你需要的是你节点的每个祖先的孩子(和爱情,根据披头士)。

获取数据

获取祖先的数组(请参见为什么在最后§)很简单:

$this->ancestors = $currentCategory->getNode()->getAncestors()->getData(); 

现在,让我们来构建它会给你你所需要的查询。假设你的模型被命名为Category,而不是Categories(它确实应该)。

$q = CategoryTable::getInstance()->createQuery('c'); 
foreach ($this->ancestors as $ancestor) 
{ 
    // should work thanks to AND priority over OR 
    $q->orWhere('c.level = ?' $ancestor->getLevel() + 1) 
    ->andWhere('c.lft > ?' $ancestor->getLeftValue()) 
    ->andWhere('c.rgt < ?' $ancestor->getRightValue()) 
} 

如果你不明白这最后一件事是什么,那么你可能需要阅读this excellent article about adjacency list model vs nested set model

现在好了,你有你的查询,让我们获取结果:

$this->categoryTree = $q->execute(
    array(), 
    Doctrine_Core::HYDRATE_RECORD_HIERARCHY); 

O_o等待......最后一个参数是关于什么的?在阅读有关嵌套集的教义文档时,您可能没有听说过它。这是因为它在the page about data hydrators上有记录。这非常糟糕,因为HYDRATE_RECORD_HIERARCHY在处理嵌套集合时非常有趣。现在,您将$ categoryTree中所需的所有内容都视为一个层次结构。无论你的树有多深,只有两个请求!我想可以写在一个请求中,但我不知道如何。

注意:还有Doctrine_Core::HYDRATE_ARRAY_HIERARCHY,它水合到一个分层阵列,这是更快。如果您不需要调用提供不属于对象一部分或者在运行时计算的东西的方法,则可以使用它。您只需在模板中使用数组而不是对象符号(例如,$categoryTree['children']

显示数据

现在,在您_menu.php模板,这里是你可以做什么:

<?php 
array_shift($ancestors); 
include_partial('level', array(
    'children' => $categoryTree->get('__children'), 
    'ancestors' => $ancestors 
); 

而且在_level.php

<ul> 
<?php $selectedChild = array_shift($ancestors); 
foreach ($children as $child): 
    if ($isSelected = ($child->getId() == $selectedChild->getId())): 
    $grandChildren = $child->get('__children'); 
    endif; ?> 
    <li<?php if ($isSelected):?> class="selected"<?php endif?>> 
    <?php echo $child->getName() ?> 
    </li> 
<?php endforeach ?>: 
</ul> 
<?php if (count($ancestors)): 
    // RecursiviRecurRecuRecursiRRecursivityecursivityvityrsivitysivityty 
    include_partial('level', array(
     'children' => $grandChildren, 
     'ancestors' => $ancestors 
    ); 
endif; ?> 

我只是写了这个未经测试任何事情,所以它从一开始就可能无法正常工作。只要让我贴出你遇到的问题。祝你好运!

+0

你好吗?任何意见?你解决了你的问题吗? – greg0ire

+0

非常感谢greg!感谢您花时间给出这样详细的回复。我使用我的Facebook帐户创建了我的堆栈溢出帐户,并且由于某种原因没有通过电子邮件告诉我您的回复...我会给它一个去,让你知道我如何得到。 –

+0

太棒了!如果您卡住了,您可以使用您提出的代码更新您的问题! – greg0ire