【问题标题】:symfony1.4 nested sets navigation through levelssymfony1.4 嵌套集导航通过级别
【发布时间】:2011-10-11 17:53:52
【问题描述】:

我目前正在学习 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

我试图构建过滤类别的二维数组,以传递给视图......但没有成功。任何解决方案都会对我有所帮助!

非常感谢,

抢劫。

【问题讨论】:

    标签: symfony1 doctrine nested-sets


    【解决方案1】:

    改写

    重新表述您的问题:您需要(您的节点和您的节点的每个祖先)及其兄弟姐妹。

    其他改写:您需要节点的每个祖先及其所有子节点(但不是所有子节点)

    并且不要认为您应该将 hasManyRoots 设置为 true,除非您有多个商店。现在假设您有一个根,您可以将其命名为“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 中拥有所需的一切作为层次结构。无论您的树有多深,都只有 2 个请求!我想可以在一个请求中编写它,但我不知道如何。

    注意:还有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; ?>
    

    我只是写了这个,没有测试任何东西,所以它可能从一开始就无法正常工作。请随时告诉我您遇到的问题。祝你好运!

    【讨论】:

    • 非常感谢格雷格!!感谢您花时间给出如此详细的回复。我使用我的 Facebook 帐户创建了我的堆栈溢出帐户,但由于某种原因没有通过电子邮件告诉我您的回复...我会试一试,让您知道我的进展情况。
    • 太棒了!如果遇到问题,您可以使用您想出的代码更新您的问题!
    • 你好啊啊啊啊?我什至没有对这个答案投赞成票,这花了我一些时间来写,而且我没有收到你的来信。发生了什么?
    • 我不是 OP,但你肯定赢得了我的支持。从未听说过层次结构隐藏。花 2 分钟阅读您的答案!
    • 谢谢,我认为这是我在这里写的最好的答案之一,但我的大部分声誉都来自对 php 标签上简单问题的简短回答......太糟糕了!无论如何,再次感谢。
    猜你喜欢
    • 2020-09-04
    • 2022-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-01
    相关资源
    最近更新 更多