Мой дубль (я знаю, что ответ принят, но я работал над этим, поэтому я опубликую id = P)
<code>// Test data
$data = array(
array('id' => 1, 'parent_id' => null, 'name' => 'lorem ipsum'),
array('id' => 2, 'parent_id' => 1, 'name' => 'lorem ipsum1'),
array('id' => 3, 'parent_id' => 1, 'name' => 'lorem ipsum2'),
array('id' => 4, 'parent_id' => 2, 'name' => 'lorem ipsum3'),
array('id' => 5, 'parent_id' => 3, 'name' => 'lorem ipsum4'),
array('id' => 6, 'parent_id' => null, 'name' => 'lorem ipsum5'),
);
// Randomize, because the data may not be in a top-down order
shuffle( $data );
// Parse and inspect the result
$builder = new TreeBuilder( $data );
echo '<pre>', print_r( $builder->getTree() ), '
';class TreeBuilder {protected $ leafIndex = array ();защищенный $ tree = array ();защищенный стек $;function __construct ($ data) {$ this-> stack = $ data;while (count ($ this-> stack)) {$ this-> branchify (array_shift ($ this-> stack));}} защищенная функция branchify (& $ leaf) {// лист корневого уровня?if (null === $ leaf ['parent_id']) {$ this-> addLeaf ($ this-> tree, $ leaf);} // Мы уже нашли родителя этого листа?иначе if (isset ($ this-> leafIndex [$ leaf ['parent_id']])) {$ this-> addLeaf ($ this-> leafIndex [$ leaf ['parent_id']] ['children'], $ leaf);} else {// Нет, поместите его обратно в стек $ this-> stack [] = $ leaf;}} защищенная функция addLeaf (& $ branch, $ leaf) {// Добавить лист в ветку $ branch [] = array ('id' => $ leaf ['id'], 'name' => $ leaf ['name'], 'data' => new stdClass, 'children' => array ());// Сохраняем ссылку, чтобы мы могли выполнить поиск O (1) позже $ this-> leafIndex [$ leaf ['id']] = & $ branch [count ($ branch) -1];} защищенная функция addChild ($ branch, $ leaf) {$ this-> leafIndex [$ leaf ['id']] & = $ branch ['children'] [] = $ leaf;} public function getTree () {return $ this-> tree;}}