A PHP class to build parent child arrays from a flat array or database query results.

I am currently developing using Kohana 3.2 PHP Framework incorporating Mustache Templates and the Twitter Bootstrap with LESS CSS and loving it. I recently wrote this simple php class to convert a flat array with id and parent_id keys into a multi-dimensional array where parents have a `children` key with children in a sub-array.

class BuildParentChild {

	private $data = array();
	public $rendered;

	public function __construct(&$Input)
	{
		foreach($Input as $Item)
		{
			$Item= (array) $Item;
			$this->data['items'][$Item['id']] = $Item;
			$this->data['parents'][$Item['parent_id']][] = $Item['id'];
			if(!isset($this->top_level) || $this->top_level > $Item['parent_id'])
			{
				$this->top_level = $Item['parent_id'];
			}
		}
		return $this;
	}

	public function build($id)
	{
		$return{$id} = array();
		foreach($this->data['parents'][$id] as $child)
		{
			$build = $this->data['items'][$child];
			if(isset($this->data['parents'][$child]))
			{
				$build['has_children'] = true;
				$build['children'] = $this->build($child);
			}
			else
			{
				$build['has_children'] = false;
			}
			$return{$id}[] = $build;
		}
		return (array) $return{$id};
	}

	public function render()
	{
		if(!isset($this->rendered) || !is_array($this->rendered))
		{
			$this->rendered = $this->build($this->top_level);
		}
		return $this->rendered;
	}
}
$Menu = new BuildParentChild($menu_items);
var_dump($Menu->render());

Consider the following table

id parent_id Name
1 0 Top
2 1 Second Level
3 2 Third Level
4 1 Another Second Level
5 0 Another Top Level

Would generate the following result.

array(
  'id' => 1,
  'name' => top,
  'has_children' => true,
  'children' => array(
    array(
      'id' => 2,
      'name' => Second Level,
      'has_children' => true,

and so on.

2 Comments

  1. Martin on August 1, 2012 at 7:50 am

    Thanks for the snippet! how would the mustache markup looking like when using as menu with ul and li? im fiddeling now a while withe your code without any success :/

    thanks anyway for sharing

    • danieliser on August 6, 2012 at 9:49 pm

      Output menu

      <ul class="nav nav-tabs">
          {{#mainmenu}}
          {{>menu}}
          {{/mainmenu}}
      </ul>

      Menu Partial

      <li class="{{#active}}active{{/active}}">
      <a href="{{url}}" 
            title="{{#title}}{{title}}{{/title}}{{^title}}{{name}}{{/title}}" 
            rel="nofollow"
          >{{name}}</a>
      
      {{#has_children}}
      <ul>
          {{#children}}
              {{>menu}}
          {{/children}}
      </ul>
      {{/has_children}}
      

Leave a Comment