symfony1.4嵌套集通过级别导航

发布于 2024-12-09 07:16:55 字数 527 浏览 0 评论 0原文

我目前正在学习 symfony1.4,并试图围绕学说的嵌套集功能进行导航,但取得的成功有限。我有一个使用多棵树的嵌套集合行为的类别表。我的类别树数据最多可达六深...

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

这些类别用于产品,我想要一个页面来过滤类别以到达叶子,以便显示该类别产品,例如,如果选择了根,则显示根,然后显示其子节点,然后如果选择了子节点,则显示其子节点,依此类推,直到选择叶节点。 这是一张可以更好地描述它的图像

我试图构建过滤类别的二维数组,传递到视图...但没有成功。任何解决方案都会有帮助,因为我的头已经炸了!

非常感谢,

罗布。

I'm currently learning symfony1.4 and am trying to navigate around the nested sets feature of doctrine with limited success. i have a category table using the nested set behaviour with mutliple trees. my category trees data can be up to six deep...

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

these categories are for products, i'd like a page to filter through the categories to reach a leaf in order to display that categories products e.g. display roots, if a root is selected, then display its children, then if a child is selected display its children, etc until you select a leaf node. here's an image which may describe it better

I was trying to build a 2 dimensional array of the filtered categories, to pass to the view... with no success. any solutions would be helpful as my head is fried!

many thanks,

rob.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

仅一夜美梦 2024-12-16 07:16:56

重新表述

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

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

并且不认为您应该将 hasManyRoots 设置为 true,除非您有多个商店。现在,假设您有一个根,您可以将其命名为“shop”。

这是第三种更简单的改写:您所需要的只是节点的每个祖先的子代(根据披头士乐队的说法,还有爱)。

获取数据

将祖先作为数组获取(请参阅最后一节中的原因)很容易:

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

现在让我们构建查询,它将为您提供所需的内容。假设您的模型被命名为 Category,而不是 Category(它确实应该如此)。

$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->categoryTree = $q->execute(
  array(), 
  Doctrine_Core::HYDRATE_RECORD_HIERARCHY);

O_o 等等...最后一个参数是什么?在阅读有关嵌套集合的学说文档时,您可能没有听说过它。这是因为它记录在有关数据水合器的页面上。这真的很糟糕,因为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; ?>

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

Rephrasing

Rephrasing your problem : you need (every ancestor of your node and your node) and their siblings.

Other rephrasing : you need every ancestor of your node along with all of their children (but not all of their descendants)

And don't think you should have hasManyRoots set to true, unless you have several shops. Now let's assume you have one root, which you could name 'shop'

Here is a third, more simple rephrasing: all you need is the children of every ancestor of your node (and love, according to the Beatles).

Fetching the data

Getting the ancestors as an array (see why in the last §) is easy :

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

Now let's build the query which will give you what you need. Let's assume your model is named Category, not Categories (it really should).

$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())
}

If you don't understand what this last thing is, then you probably need to read this excellent article about adjacency list model vs nested set model

Ok now that you have your query, let's fetch the results:

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

O_o wait... what was that last parameter about? You probably didn't hear about it when reading the doctrine documentation about nested set. That's because it is documented on the page about data hydrators. This really sucks, because HYDRATE_RECORD_HIERARCHY is very interesting when working with nested sets. Now what you have everything you need in $categoryTree as a hierarchy. With only 2 requests no matter how deep your tree is! I guess one could write it in one request, but I don't see how.

Note: there also is Doctrine_Core::HYDRATE_ARRAY_HIERARCHY, which hydrates to a hierarchical array, which is much faster. You can use it if you don't need to call methods that provide stuff that is not part of your object, or that is computed at run time. You'll just have to use array instead of object notation in your template (e.g. $categoryTree['children'])

Displaying the data

Now in your _menu.php template, here is what you can do:

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

And in _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; ?>

I just wrote this without testing anything, so it will probably not work right from the start. Just keep me posted with the problems you have. Good luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文