Вложенные symfony1.4 устанавливает навигацию по уровням - PullRequest
1 голос
/ 11 октября 2011

В настоящее время я изучаю symfony1.4 и пытаюсь ориентироваться в особенностях вложенных множеств в доктрине с ограниченным успехом.у меня есть таблица категорий, использующая поведение вложенного множества с деревьями-множествами.мои данные дерева категорий могут быть до шести глубоких ...

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

эти категории для продуктов, я хотел бы страницу для фильтрации по категориям, чтобы достичь листа, чтобы отобразить продукты этих категорийнапример, отображать корни, если выбран корень, затем отображать его дочерние элементы, затем, если выбран дочерний элемент, отображать его дочерние элементы и т. д., пока не будет выбран конечный узел. вот изображение, которое может описать его лучше

Я пытался создать двумерный массив отфильтрованных категорий, чтобы перейти к представлению ... безуспешно.любые решения были бы полезны, так как моя голова жарена!

большое спасибо,

rob.

1 Ответ

5 голосов
/ 13 октября 2011

Перефразируя

Перефразируя вашу проблему: вам нужны (каждый предок вашего узла и вашего узла) и их братья и сестры.

Другое перефразирование: вам нужен каждый предок вашего узла вместе со всеми их детьми (но не со всеми их потомками)

И не думайте, что для 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; ?>

Я просто написал это, ничего не тестируя, поэтому, вероятно, он не будет работать с самого начала. Просто держите меня в курсе проблем, которые у вас есть. Удачи!

...