Получить все дочерние, внуки и т. Д. Узлы под родителями, используя php с результатами запроса mysql

Я пытался понять это, но я никуда не ушел. Надеюсь, кто-то может прийти на помощь.

Моя проблема заключается в том, что я использую модель данных списка смежности для создания моих данных иерархии в mysql. Я могу получить таблицу (см. Ниже) в массив многомерных измерений с ассоциативным массивом для каждого элемента. То, что я хочу сделать, – это как только я получу этот массив, я хочу получить еще один массив со всеми узлами (дочерний, внук и т. Д.) Под родительским идентификатором (включая родительский элемент). Я просто не могу тренироваться, как кодировать tihs в PHP.

В MySQL моя таблица выглядит следующим образом:

id name parent_id 1 Electronics 0 2 Televisions 1 3 Portable Electronics 1 4 Tube 2 5 LCD 2 6 Plasma 2 7 Mp3 Players 3 8 CD Players 3 9 2 Way Radios 3 10 Flash 7 

Я могу получить все строки с этим кодом в ассоциативный массив с этим.

 $r = mysql_query("SELECT * FROM test "); $data = array(); while($row = mysql_fetch_assoc($r)) { $data[] = $row; } 

Получает результаты:

 Array ( [0] => Array ( [id] => 1 [name] => Electronics [parent_id] => 0 ) [1] => Array ( [id] => 2 [name] => Televisions [parent_id] => 1 ) [2] => Array ( [id] => 3 [name] => Portable Electronics [parent_id] => 1 ) [3] => Array ( [id] => 4 [name] => Tube [parent_id] => 2 ) [4] => Array ( [id] => 5 [name] => LCD [parent_id] => 2 ) [5] => Array ( [id] => 6 [name] => Plasma [parent_id] => 2 ) [6] => Array ( [id] => 7 [name] => Mp3 Players [parent_id] => 3 ) [7] => Array ( [id] => 8 [name] => CD Players [parent_id] => 3 ) [8] => Array ( [id] => 9 [name] => 2 Way Radios [parent_id] => 3 ) [9] => Array ( [id] => 10 [name] => Flash [parent_id] => 7 ) ) 

С этим результатом я хочу отфильтровать его с помощью id.

Скажем, например, мне нужен ассоциативный массив каждого узла в Portable Electronics с идентификатором 3. (Использовать идентификатор для кода)

Он вернет массив с строками с идентификаторами:

  • 3 Переносная электроника (должен быть включен выбранный родитель)
  • 7 Mp3-плееры (ребенок)
  • 8 проигрывателей компакт-дисков (ребенок)
  • 9 двухсторонних радиоприемников (ребенок)
  • 10 Вспышка (Великий Ребенок)

если бы у Flash были дети, они тоже вернули бы их.

Таким образом, конечный результат возвращает массив, подобный выше, но только с этими элементами.

Обратите внимание: я не выполняю функцию, которая создает массив многомерных данных из древовидной структуры (уже получил решение для этого). Я хочу построить функцию: fetch_recursive ($ id), которая получает идентификатор и возвращает все элементы в этот уровень и уровни ниже и т. д. и т. д.

Надеюсь это поможет

заранее спасибо

Редактировать:

Ранее я опубликовал решение для построения многомерного массива из полученного вами вывода, а также способ получить все дочерние элементы определенного id из этого конкретного массива. Теперь я понял, как извлекать дочерние элементы прямо из вашего вывода (без необходимости сначала buildtree() функцию buildtree() :

 function fetch_recursive($src_arr, $currentid, $parentfound = false, $cats = array()) { foreach($src_arr as $row) { if((!$parentfound && $row['id'] == $currentid) || $row['parent_id'] == $currentid) { $rowdata = array(); foreach($row as $k => $v) $rowdata[$k] = $v; $cats[] = $rowdata; if($row['parent_id'] == $currentid) $cats = array_merge($cats, fetch_recursive($src_arr, $row['id'], true)); } } return $cats; } 

Чтобы использовать вышеприведенную функцию, просто передайте в выходной массив $data первый аргумент и id вы хотите получить дочерние элементы во втором аргументе:

напр .:

 $list = fetch_recursive($data, 3); 

Что должно дать вам правильную структуру массива для id 3 (как видно из примера в последнем коде для этого ответа).


Оригинальный ответ:

Мне никогда не приходилось писать рекурсивную функцию для создания вложенных деревьев из этого проекта до сих пор. Я уверен, что есть много других, которые написали подобные функции, но этот должен определенно работать на вас:

 function buildtree($src_arr, $parent_id = 0, $tree = array()) { foreach($src_arr as $idx => $row) { if($row['parent_id'] == $parent_id) { foreach($row as $k => $v) $tree[$row['id']][$k] = $v; unset($src_arr[$idx]); $tree[$row['id']]['children'] = buildtree($src_arr, $row['id']); } } ksort($tree); return $tree; } с function buildtree($src_arr, $parent_id = 0, $tree = array()) { foreach($src_arr as $idx => $row) { if($row['parent_id'] == $parent_id) { foreach($row as $k => $v) $tree[$row['id']][$k] = $v; unset($src_arr[$idx]); $tree[$row['id']]['children'] = buildtree($src_arr, $row['id']); } } ksort($tree); return $tree; } 

Эта функция рекурсивно построит дерево из списка смежности и сохранит идентификатор в порядке возрастания. Это также делает id каждого родителя / дочернего элемента ключом каждого массива информации.

Этот код:

 $r = mysql_query("SELECT * FROM test "); $data = array(); while($row = mysql_fetch_assoc($r)) { $data[] = $row; } echo '<pre>'; print_r(buildtree($data)); echo '</pre>'; 

Выведет что-то вроде этого:

 Array ( [1] => Array ( [id] => 1 [name] => Electronics [parent_id] => 0 [children] => Array ( [2] => Array ( [id] => 2 [name] => Televisions [parent_id] => 1 [children] => Array ( [4] => Array ( [id] => 4 [name] => Tube [parent_id] => 2 [children] => Array() ) [5] => Array ( [id] => 5 [name] => LCD [parent_id] => 2 [children] => Array() ) [6] => Array ( [id] => 6 [name] => Plasma [parent_id] => 2 [children] => Array() ) ) ) [3] => Array ( [id] => 3 [name] => Portable Electronics [parent_id] => 1 [children] => Array ( [7] => Array ( [id] => 7 [name] => Mp3 Players [parent_id] => 3 [children] => Array ( [10] => Array ( [id] => 10 [name] => Flash [parent_id] => 7 [children] => Array() ) ) ) [8] => Array ( [id] => 8 [name] => CD Players [parent_id] => 3 [children] => Array() ) [9] => Array ( [id] => 9 [name] => 2 Way Radios [parent_id] => 3 [children] => Array() ) ) ) ) ) ) 

Чтобы получить все дочерние узлы определенного id на одномерный массив, вы можете использовать эту функцию:

 function fetch_recursive($tree, $parent_id, $parentfound = false, $list = array()) { foreach($tree as $k => $v) { if($parentfound || $k == $parent_id) { $rowdata = array(); foreach($v as $field => $value) if($field != 'children') $rowdata[$field] = $value; $list[] = $rowdata; if($v['children']) $list = array_merge($list, fetch_recursive($v['children'], $parent_id, true)); } elseif($v['children']) $list = array_merge($list, fetch_recursive($v['children'], $parent_id)); } return $list; } 

Основываясь на buildtree() функции buildtree() , предположим, что мы хотим получить все дочерние узлы id 3:

 echo '<pre>'; print_r(fetch_recursive(buildtree($a), 3)); echo '</pre>'; 

Это приведет к выводу:

 Array ( [0] => Array ( [id] => 3 [name] => Portable Electronics [parent_id] => 1 ) [1] => Array ( [id] => 7 [name] => Mp3 Players [parent_id] => 3 ) [2] => Array ( [id] => 10 [name] => Flash [parent_id] => 7 ) [3] => Array ( [id] => 8 [name] => CD Players [parent_id] => 3 ) [4] => Array ( [id] => 9 [name] => 2 Way Radios [parent_id] => 3 ) ) 

Ниже приведен способ получить вас дальше, и вы можете решить, как вы создаете массив результатов и какие поля вы хотите включить. Это не проверено, но вы должны увидеть логику.

 // connect to db // set id counter $ids = 0; // declare array $categories = new Array(); // determine max ids $query = mysql_query("SELECT COUNT(1) AS ids FROM test"); $result = mysql_fetch_array(query); // get result $count = $result['ids']; // loop through ids for parents for($ids = 0; $ids <= $count; $ids++) { $query1 = mysql_query("SELECT * FROM test WHERE id = '" . $ids . "'"); $query2 = mysql_query("SELECT id, name, parent_id FROM test WHERE parent_id = '" . $ids . "'"); // check if has children if(mysql_num_rows($query2) > 0) { // iterate through children and add to array while (mysql_fetch_array($query2) as $row) { $categories[$ids]['child'][$row['id']] = $row['name']; } } // check if has siblings if(mysql_num_rows($query1) > 0) { // iterate through children and add to array while (mysql_fetch_array($query2) as $row) { $categories[$ids]['sibling'][$row['id']] = $row['name']; } } }