Получите все дочерние, внуки и т. д. узлы под родителем, используя 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'];
    }
  }
}