11

私はこれを理解しようとしてきましたが、どこにも行きませんでした。誰かが私の救助に来ることができれば幸いです。

私の問題は、隣接リストデータモデルを使用してmysqlで階層データを生成していることです。テーブル(以下を参照)を、各アイテムの連想配列を持つ多次元配列に取得できます。私がやりたいのは、この配列を取得したら、親ID(親アイテムを含む)の下にすべてのノード(子、孫など)を含む別の配列を取得したいです。 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双方向ラジオ(子供)
  • 10フラッシュ(孫)

Flashに子があった場合、それらも返されます。

したがって、最終結果は上記のような配列を返しますが、これらのアイテムのみが含まれます。

注意:私はツリー構造の多次元配列を作成する関数を求めていません(その解決策はすでにあります)。IDを受け取り、のすべてのアイテムを返す関数fetch_recursive($ id)を作成したいと思います。そのレベルとその下のレベルなど。

お役に立てれば

前もって感謝します

4

2 に答える 2

19

編集:

私は以前、あなたが与えた出力から多次元配列を構築するためのソリューションと、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で、2番目の引数から子要素を取得します。

元。:

$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()
                    )
                )
            )
        )
    )
)

特定のすべての子ノードをid1次元配列に取得するには、次の関数を使用できます。

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;
}

上記の関数に基づいて、3buildtree()のすべての子ノードを取得したいとします。id

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
        )

)
于 2012-07-16T03:16:27.467 に答える
0

これがあなたをさらに前進させる方法であり、あなたはあなたの結果配列をどのように構築するか、そしてあなたがどのフィールドを含めることを選択するかを決めることができます。これはテストされていませんが、ロジックが表示されるはずです。

// 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'];
    }
  }
}
于 2012-07-16T03:12:10.270 に答える