改写
重新表述您的问题:您需要(您的节点和您的节点的每个祖先)及其兄弟姐妹。
其他改写:您需要节点的每个祖先及其所有子节点(但不是所有子节点)
并且不要认为您应该将 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; ?>
我只是写了这个,没有测试任何东西,所以它可能从一开始就无法正常工作。请随时告诉我您遇到的问题。祝你好运!