簡體   English   中英

使用帶有mysql查詢結果的php獲取父級下的所有子級,孫級等節點

[英]Get all child, grandchild etc nodes under parent using php with mysql query results

我一直試圖解決這個問題,但我沒有到達任何地方。希望有人可以來救我。

我的問題是我使用鄰接列表數據模型在mysql中生成我的層次結構數據。我可以將表(見下文)檢索到一個多維數組中,每個項目都有一個關聯數組。 我想要做的是,一旦我得到這個數組,我想得到另一個數組,包含父ID(包括父項)下的所有節點(子,孫等)。我只是無法鍛煉如何編碼tihs in 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過濾掉它。

比方說,我想要一個ID為3的便攜式電子設備下的每個節點的關聯數組。(代碼使用id)

它將返回一個包含id的行數組:

  • 3便攜式電子產品(必須包括選定的父母)
  • 7個Mp3玩家(兒童)
  • 8名CD播放器(兒童)
  • 9 2路無線電(兒童)
  • 10 Flash(大孩子)

如果Flash有孩子,它也會返回。

因此最終結果將返回一個類似上面的數組,但只返回那些項目。

請注意:我不是在創建樹結構的多維數組的函數之后(已經有了解決方案)。我想構建一個函數:fetch_recursive($ id),它接收一個ID並返回所有項目那個級別和等級以下等等。

希望這可以幫助

提前致謝

編輯:

我之前發布過一個解決方案,用於根據您提供的輸出構建多維數組,以及一種從特定數組中獲取特定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傳遞給第一個參數,並將要從第二個參數中檢索子元素的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;
}

此函數將以鄰接列表的形式遞歸構建樹,並按升序對id進行排序。 這也使得每個父/子的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()函數,假設我們想要獲取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'];
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM