Перефразируя
Перефразируя вашу проблему: вам нужны (каждый предок вашего узла и вашего узла) и их братья и сестры.
Другое перефразирование: вам нужен каждый предок вашего узла вместе со всеми их детьми (но не со всеми их потомками)
И не думайте, что для hasManyRoots должно быть установлено значение true, если только у вас нет нескольких магазинов. Теперь давайте предположим, что у вас есть один корень, который вы можете назвать «магазин»
Вот третье, более простое перефразирование: все, что вам нужно, это дети каждого предка вашего узла (и любви, согласно Битлз).
Извлечение данных
Получить предков в виде массива (см. Почему в последнем §) легко:
$this->ancestors = $currentCategory->getNode()->getAncestors()->getData();
Теперь давайте создадим запрос, который даст вам то, что вам нужно. Давайте предположим, что ваша модель называется Категория, а не Категории (это действительно должно быть).
$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);
О_о подожди ... что это был за последний параметр? Вы, вероятно, не слышали об этом при чтении документации доктрины о вложенном множестве. Это потому, что это задокументировано на странице о гидраторах данных . Это действительно отстой, потому что 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; ?>
Я просто написал это, ничего не тестируя, поэтому, вероятно, он не будет работать с самого начала. Просто держите меня в курсе проблем, которые у вас есть. Удачи!