I’m currently working on a Symfony project with a lot of hierarchical data. For this I have taken advance of the new Nested Set implementation in Propel 1.3. Even though some initial research on Google showed a few people complaining about Propels implementation, I decided to give it a try. My schema.yml

team:
  _attributes:
    treeMode: NestedSet
  id:
    company_id:
      type: integer
      treeScopeKey: true
    name:
      type: VARCHAR
      size: 128
      required: true
    lft:
      type: integer
      required: true
      default: 0
      nestedSetLeftKey: true
    rgt:
      type: integer
      required: true
      default: 0
      nestedSetRightKey: true

Currently the only problem I have had is when I need to reassign a new node as root node. My first thought was to make the new node root and add the old root node as child, but Propel doesn’t like that and messes up the left-right values. What I have done is to insert the new node as child of the root node and then swap left-right values, like this:

$node = new Team();
$root = TeamPeer::retrieveRoot($scopeId);
$node->insertAsFirstChildOf($root);

// Swap left-right values
$rootRight = $root->getRightValue();
$root->setLeftValue($node->getLeftValue());
$root->setRightValue($node->getRightValue());

// Make node root
$node->setLeftValue(1);
$node->setRightValue($rootRight);

Display tree using RecursiveIteratorIterator

I retrieve the tree with the static peer method retrieveTree() and display it using the RecursiveIteratorIterator.

$tree = TeamPeer::retrieveTree($scopeId);
$it = new RecursiveIteratorIterator($tree, RecursiveIteratorIterator::SELF\_FIRST); 
foreach ($it as $item) { echo $item; }

However I wanted to print the items as an indented “list” in a dropdown box. For this I extended the RecursiveIteratorIterator class and implemented its beginChildren() and endChildren() methods.

class MyIndentRecursiveIteratorIterator extends RecursiveIteratorIterator {
  private $indent = '';
  private $indentStr = '  ';
  
  public function getIndent() {
    return $this->indent;
  }
  
  public function beginChildren() {
    $this->indent = str\_repeat($this->indentStr, $this->getDepth());
  }
    
  public function endChildren() {
    $this->indent = str\_repeat($this->indentStr, $this->getDepth() - 1);
  }
}

$tree = TeamPeer::retrieveTree($scopeId);
$it = new MyIndentRecursiveIteratorIterator($tree, MyIndentRecursiveIteratorIterator::SELF\_FIRST);
foreach ($it as $item) { echo $it->getIndent() . $item; }

Which produces something like below which can be used in a dropdown or similar.

Root
  Child 1
    Child 1.1
    Child 1.2
  Child 2

Updated: