Nested Set in Propel 1.3

Im 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

2 thoughts on “Nested Set in Propel 1.3”

  1. cool!
    exactly that example, i was looking for. need not idention but json-code. had no idea, how to return the values from ‘beginChildren()’ and ‘endChildren()’.
    thanks
    roelfsche

Leave a Reply

Your email address will not be published. Required fields are marked *