symfony - nestedSet и рендеринг родительских / дочерних узлов - PullRequest
4 голосов
/ 12 мая 2011

Я создал модель, использующую поведение доктрины nestedSet в Symfony1.4, так как я пытаюсь создать базовый cms с иерархическими страницами.

У меня есть пара страниц, с родителем и потомкомузлы

Parent_1
   Child_1
   Child_2
Parent_2
   Child_3

Моя проблема связана с отображением этих элементов в виде заголовка навигации.(<ul><li> и т. Д.)

Какой самый простой / лучший способ сделать это?

Я бы хотел, чтобы у узлов root были URL-адреса, такие как /parent_1 и последующие дочерние узлы.узлы, быть parent_1/child_1

Спасибо

Ответы [ 2 ]

2 голосов
/ 12 мая 2011

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

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

<?php
//Render a nested set.  Recurses for all descendants of that node. Can be used to draw entire tree, when specifying root id.
//Secondary parameter ($node) is used for performance boost, internally in function.
public static function display_node($id, $node = null) {

    $isRoot = false;

    if ($node == null) {
        $node = Doctrine_Core::getTable('YOURNESTEDTABLENAME')->findOneById($id)->getNode();
        if ($node->isRoot()) {
            $isRoot = true;
        }
    }
    $record = $node->getRecord();

    if (!$isRoot) {
        echo "<li class='tree_item' id='list_". $record->getId() . "'>"; 
        echo "<div class='listitem' id='listitem_".$record->getId()."'>";
        echo $record->getName();
        echo "<div style='clear:both'></div>";
        echo "</div>";

        if ($node->hasChildren()) {
            echo "<ol>";
            foreach ($node->getChildren() as $child) {
                self::display_node($child->getId(), $child->getNode());
            }
            echo "</ol>";
        }
    }
    else {
        if ($node->hasChildren()) {
            echo "<ol class='sortable'>";
            echo "<li class='tree_item root_item' style='position: relative;' id='list_". $record->getId() . "'>";
            foreach ($node->getChildren() as $child) {
                self::display_node($child->getId(), $child->getNode());
            }
            echo "</ol>";
        }
    }
}
?>

Вы также можете легко изменить код для добавления URL-адресов по своему усмотрению. Надеюсь, это поможет. Дайте мне знать, если вам потребуются разъяснения.

1 голос
/ 12 мая 2011

Ненавижу отображать элементы в любом месте, кроме шаблонов, так что вот моя версия.

//actions:
    public function executeShow(sfWebRequest $request)
    {
      $this->tree = Doctrine::getTable('Model')->getMenuTree();
    }

//lib:
    class ModelTable extends Doctrine_Table
    {
      /**
       * Gets tree element in one query
       */
      public function getMenuTree()
      {

        $q = $this->createQuery('g')
          ->orderBy('g.root_id')
          ->addOrderBy('g.lft')
          ->where('g.root_id NOT NULL');

        return $q->execute(array(),  Doctrine_Core::HYDRATE_ARRAY_HIERARCHY);
      }
    }

//template:

<?php function echoNode($tree, $parent=null) { ?>
  <ul>
  <?php foreach ($tree as $node): ?>
    <li data-id='<?php echo $node['id'] ?>'>
      <?php echo $node['name'] ?>
      <?php if (count($node['__children']) > 0): ?>
        <?php echo echoNode($node['__children'], $node) ?>
      <?php endif; ?>
    </li>
  <?php endforeach; ?>       
  </ul>
<?php } ?>

<?php echo echoNode($tree) ?>

Теперь, если вам нужна часть дерева, вы можете выполнить действие или, что еще лучше, написать для этого отдельный метод модели.

...