Я пытался понять это, но я никуда не ушел. Надеюсь, кто-то может прийти на помощь.
Моя проблема заключается в том, что я использую модель данных списка смежности для создания моих данных иерархии в 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. (Использовать идентификатор для кода)
Он вернет массив с строками с идентификаторами:
если бы у 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']; } } }