Search code examples
symfony1symfony-1.4

symfony - nestedSet and rendering of parent/child nodes


I have created a model using the doctrine nestedSet behaviour in Symfony1.4, as I'm trying to create a basic cms, with heiracrchial pages.

I have a couple of pages, with parent and child nodes

Parent_1
   Child_1
   Child_2
Parent_2
   Child_3

My problem comes with rendering these items in terms of a navigation header. (<ul><li> etc)

What would be the easiest/best way to do this?

I'd like the root nodes to have URLs such as /parent_1 and subsequent child nodes, be parent_1/child_1

Thanks


Solution

  • I wrote a recursive function that will draw the tree starting from any node. Specifying the root node will draw the entire tree. It is used in my cart plug-in, and you can view a demo of the completed UI here.

    I have pasted the function below, but modified it from my implementation to make it more clear.

    <?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>";
            }
        }
    }
    ?>
    

    You can also easily modify the code to add URLs as you wish. Hopefully this helps. Let me know if you require clarification.