Получите все дочерние, внуки и т. д. узлы под родителем, используя 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
)
)
С этим результатом я хочу, чтобы отфильтровать его с идентификатором.
скажем, например, я хотел ассоциативный массив каждого узла под портативной электроникой с идентификатором 3.(Используйте id для кода)
он вернет массив со строками с идентификаторами:
- 3 портативная электроника (выбранный родитель должен быть включен)
- 7 Mp3-Плееры (Ребенок)
- 8 CD-плееры (ребенок)
- 9 2 способ Радио (ребенок)
- 10 Вспышка (Grand Child)
если бы у Flash были дети, он вернул бы и их.
таким образом, конечный результат вернет массив, подобный приведенному выше, однако только с этими элементами.
пожалуйста отмечать: Мне не нужна функция, которая создает многозначный массив древовидной структуры (для этого уже есть решение) .Я хочу построить функцию: fetch_recursive ($id), которая получает ID и возвращает все элементы на этом уровне и на уровнях ниже и т. д.
надеюсь, что это помогает
спасибо заранее
2 ответов
Edit:
я ранее опубликовал решение для построения многомерного массива из выходных данных, которые вы дали, а также способ получить все дочерние элементы конкретного id
из этого конкретного массива. Теперь я понял, как получить дочерние элементы прямо из вашего вывода (без необходимости сначала проходить через 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
к первому аргументу и the id
вы хотите получить дочерние элементы из второго аргумента:
ex.:
$list = fetch_recursive($data, 3);
, который должен дать вам правильную структуру массива для id
3
(как видно из примера в последнем codebox к этому ответу).
Оригинальный Ответ:
до сих пор я никогда не писал рекурсивную функцию для построения вложенных деревьев из этого дизайна. Я уверен, что есть много других, которые написали аналогичные функции, но это должно работать для вас:
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
' s каждого родителя/ребенка ключ каждого массива информации.
этот код:
$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()
функция выше, скажем, мы хотели получить все дочерние узлы 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'];
}
}
}