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

此时,您会注意到有一个名为“children”的额外层会打乱您的深度计数。发生这种情况是因为节点的后代被放入他们自己的数组中。您可以跳过打印这些行,并发出有关数组中项目的更多数据,如下所示:

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

我的最终解决方案具有无限深度,只有一个查询,表中的所有信息以及对RecursiveIteratorIterator的所有功能(如childrendepth )的访问。我在我的解决方案中使用了两个数组。

平面阵列

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。

你现在有两个数组:

  • $info - (flat) 包含关于你的节点的所有信息
  • $struc - (递归)包含节点的结构

递归数组迭代器

开始使用 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 回答