1

RecursiveArrayIterator のパラメーターとして渡される再帰配列をどのように構造化するかの例を探しています。ID、parent_id、およびタイトルを持つmysqlテーブルがあります。

id    parent_id   title
-----------------|-------------------
1         0      | Item 1
2         1      | Item 2
3         1      | Item 3
4         3      | Item 4
5         4      | Item 5

ツリー、メニュー、オプションなどを構築するために RecursiveArrayIterator に渡すことができるテーブルから配列を作成したいと思います。この「build_tree」関数https://stackoverflow.com/a/8587437/1746522を試して、mysql テーブルから配列を作成しました。結果の配列は次のようになります。

array (size=2)
  0 => 
    array (size=3)
      'id' => string '1' (length=1)
      'title' => string 'Item 1' (length=6)
      'parent_id' => string '0' (length=1)
      'children' => 
        array (size=2)
          0 => 
            array (size=3)
              ...
          1 => 
            array (size=3)
              ...

しかし、結果の配列を RecursiveArrayIterator に渡すと、奇妙に見えます。たとえば、この関数を使用すると:

$array = new RecursiveArrayIterator($tree);
$iterater = new RecursiveIteratorIterator($array);  
foreach ($iterater as $key => $value) {
    $d = $iterater->getDepth();            
    echo "depth=$d k=$key v=$value\n";
}

次のような奇妙で使用できない出力があります。

depth=0 k=0 v=Array
depth=1 k=id v=1
depth=1 k=title v=Item 1
depth=1 k=parent_id v=0
depth=2 k=0 v=Array
depth=3 k=id v=2
depth=3 k=title v=Item 2
depth=3 k=parent_id v=1
depth=4 k=0 v=Array
....

深さが間違っており、要素ではなく単一の値を反復処理します。おそらく RecursiveArrayIterator に渡された配列は「不正な形式」であり、他の方法で構造化する必要がありますか?

私はこのようなものを見ることを期待していました:

depth=0 k=1 v=Array
depth=1 k=2 v=Array
depth=1 k=3 v=Array

ここで、Array には、parent_id や title などのノードへのすべての値が含まれ、k は mysql 列 ID の ID です。

4

2 に答える 2

2

デフォルトでは、RecursiveIteratorIteratorクラスはツリーの「葉」のみを表示します。つまり、配列ではないツリー内のすべてです。

イテレータを初期化して、配列ノードとリーフを表示したいとします。次に、配列であるノードのデータのみを出力したいとします。

$array = new RecursiveArrayIterator($records);
$iterater = new RecursiveIteratorIterator($array, RecursiveIteratorIterator::SELF_FIRST);  
foreach ($iterater as $key => $value) {
    if (is_array($value)) {
        $d = $iterater->getDepth(); 
        echo "depth=$d k=$key value=$value\n";
    }
}

> depth=0 k=0 value=Array
> depth=0 k=1 value=Array
> depth=1 k=children value=Array
> depth=2 k=0 value=Array
> depth=2 k=1 value=Array

この時点で、深度カウントを台無しにする「子」と呼ばれる余分なレイヤーがあることに気付くでしょう。これは、ノードの子孫が独自の配列に配置されるために発生します。これらの行の出力をスキップして、次のように配列内の項目に関するデータをさらに出力できます。

foreach ($iterater as $key => $value) {
    if (is_array($value) && $key !== 'children') {
        $d = $iterater->getDepth(); 
        echo "depth=$d k=$key title={$value['title']}\n";
    }
}
于 2013-01-29T18:09:36.760 に答える
0

無制限の深さ、1 つのクエリのみ、テーブルからのすべての情報、およびchildrendepthなどのRecursiveIteratorIteratorのすべての関数へのアクセスを備えた私の最終的なソリューション。私のソリューションでは 2 つの配列を使用しています。

フラット配列

select * from table

通常どおりフラット配列を作成します。

$info[1] = array('parent_id' => 0, 'title' => 'Item 1');
$info[2] = array('parent_id' => 1, 'title' => 'Item 2');
$info[3] = array('parent_id' => 1, 'title' => 'Item 3');
$info[4] = array('parent_id' => 3, 'title' => 'Item 4');
$info[5] = array('parent_id' => 4, 'title' => 'Item 5');

id列を配列インデックスとして使用します。

ネストされた配列

項目の ID のみを含む$infoからネストされた配列を作成します。

function tree_structure($info, $parent = 0) {    
    foreach ($info as $row) {
        if ($row['parent_id'] == $parent)
            $struc[$row['id']] = tree_structure($info, $row['id']);
    }    
    return $struc;        
}

この配列は RecursiveArrayIterator に渡すことができます。

これで 2 つの配列ができました。

  • $info - (フラット) ノードに関するすべての情報が含まれます
  • $struc - (再帰的) ノードの構造を含みます

RecursiveArrayIterator

RecursiveArrayIterator の使用を開始する

    $array = new RecursiveArrayIterator($struc);
    $iterator = new RecursiveIteratorIterator($array, TRUE);
    $iterator->rewind();

    while ($iterator->valid()) {
        // Get the id
        $iterator->key();
        // Get the depth
        $iterator->getDepth();
        // Check if it has children
        $iterator->hasChildren();
        // Get the number of children
        sizeof($iterator->callGetChildren());
        // Get all information for the node from the flat array
        $info[$iterator->key()];

        $iterator->next();
    }

コード内の$info[$iterator->key()]行が実際のトリックを実行します。この行を使用すると、構造を台無しにすることなく、ノードに関するすべての情報を取得できます。

于 2013-01-29T22:55:39.590 に答える