PHP-如何访问深度数组';的内容,动态构建指向它的路径

PHP-如何访问深度数组';的内容,动态构建指向它的路径,php,arrays,multidimensional-array,hierarchy,hierarchical-data,Php,Arrays,Multidimensional Array,Hierarchy,Hierarchical Data,我正在尝试用PHP构建一个层次结构数组,该数组来自使用闭包表存储的关系数据库内容。对于给定的结果,我将拥有LEAF节点的完整路径,下面的内容看起来像我的结果集 1~根~根节点 1~根~根节点>>>2~类别1~第一类 1~根~根节点>>>3~类别2~第二类 1~根~根节点>>>2~类别1~第一类>>>4~子类别1~第一类的子类别 总之,这些是我的数据库结果。因此,我想遍历它们并在PHP中构建一个层次结构,以便将其转换为JSON并在DOJO中呈现一棵树 因此,当我遍历每一行时,我正在构建一条到叶子的

我正在尝试用PHP构建一个层次结构数组,该数组来自使用闭包表存储的关系数据库内容。对于给定的结果,我将拥有
LEAF
节点的完整路径,下面的内容看起来像我的结果集

1~根~根节点

1~根~根节点>>>2~类别1~第一类

1~根~根节点>>>3~类别2~第二类

1~根~根节点>>>2~类别1~第一类>>>4~子类别1~第一类的子类别

总之,这些是我的数据库结果。因此,我想遍历它们并在PHP中构建一个层次结构,以便将其转换为JSON并在DOJO中呈现一棵树

因此,当我遍历每一行时,我正在构建一条到叶子的“路径”,因为当元素是“叶子”时,我只需要向树中添加一个元素。。。基于这种想法,我决定标记每个结果,使用“>>>”作为分隔符,给我该行中的节点。然后我循环遍历这些节点,通过“~”标记每个节点,这给了我每个节点的属性

因此,我有一个for循环来处理每一行,它基本上确定如果正在处理的节点不是一个叶,那么将它的ID添加到一个数组中,该数组将跟踪路径以到达最终将要处理的叶。然后,当我最终到达叶子时,我可以调用一个函数来插入一个节点,使用我一直编译的路径

希望这一切都有意义。。所以我在下面加入了代码。。考虑上面的第二个结果。当我处理完整个结果并准备调用函数insertNodeInTreeV2()时,数组如下所示

$fullTree
是一个包含1个元素的数组,索引位置为[1] 该元素包含一个包含四个元素的数组:
ID(1)
名称(根)
说明(根节点)
子元素(空数组)

$pathEntries
是一个只有一个元素(1)的数组。这意味着要插入的叶节点的路径由节点[1]确定,节点[1]是根节点

$nodeToInsert
是一个包含四个元素的数组:
ID(2)
名称(类别1)
说明(第一类)
子元素(空数组)

$treeRootPattern
是一个字符串,其中包含用于存储整个数组/树的变量名,在本例中为“fullTree”

因此,当我进行赋值时,$treeVar=$$compiledPath;,我想我正在将变量$treeVar设置为等于$fullTree[1]['CHILDREN'](我已经在调试器中验证了它是一个有效的数组索引)。即使我将$compiledPath的内容粘贴到Eclipse调试器中的一个新表达式中,它也会显示一个空数组,这很有意义,因为它位于$fullTree[1]['CHILDREN'中]

但是,运行时告诉我以下错误

troller.php第85行-未定义变量:fullTree[1]['CHILDREN']

在此方面的任何帮助都将不胜感激。。。如果你有更好的方法让我从我描述的结果集中得到我正在尝试构建的分层数组,我会渴望采用更好的方法

更新后添加了调用上述函数的代码——FOR循环处理数据库结果行,如上所述

foreach ( $ontologyEntries as $entry ) {

        // iterating over rows of  '1~~root~~The root node>>>2~~category1~~The first category
        $nodes = explode( '>>>', $entry['path'] );
        $numNodes = count( $nodes ) - 1 ;

        $pathToNewNode = null;  // this is the path, based on ID, to get to this *new* node
        for ( $level = 0; $level <= $numNodes; $level++ ) {

            // Parse the node out of the database search result
            $thisNode = array(
                'ID'          => strtok($nodes[$level], '~~'),  /*   1   */
                'NAME'        => strtok( '~~'),                 /*   Root   */
                'DESCRIPTION' => strtok( '~~'),                 /*   This is the root node   */
                'CHILDREN'    => array()
            );

            if ( $level < $numNodes ) {   // Not a leaf, add it to the pathToThisNodeArray
                $pathToNewNode[] = $thisNode['ID'];
            }
            else {
                // processing a leaf, add it to the array
                $this->insertNodeInTreeV2( $$treeRootPattern,  $pathToNewNode, $thisNode, $treeRootPattern );
            }

        }

    }
foreach($ontologyEntries作为$entry){
//正在“1~~根~~根节点>>>2~~类别1~~第一个类别”的行上迭代
$nodes=explode(“>>>”,$entry['path']);
$numNodes=计数($nodes)-1;
$pathToNewNode=null;//这是基于ID的到达此*新*节点的路径
对于($level=0;$level strtok($nodes[$level],“~~”),/*1*/
'NAME'=>strtok('~~'),/*Root*/
'DESCRIPTION'=>strtok('~~'),/*这是根节点*/
'CHILDREN'=>array()
);
如果($level<$numNodes){//不是叶,请将其添加到pathToThisNodeArray
$pathToNewNode[]=$thisNode['ID'];
}
否则{
//处理叶,将其添加到数组中
$this->insertNodeInTreeV2($$treeRootPattern、$pathToNewNode、$thisNode、$treeRootPattern);
}
}
}

有关解释,请参见问题下方的我的评论

$paths = array(
    "1~root~the root node",
    "1~root~the root node>>>2~category1~First category",
    "1~root~the root node>>>3~category2~Second category",
    "1~root~the root node>>>2~category1~First category>>>4~subCatOfCategory1~SubCategory of Cat 1"
);

$tree = array();

foreach ($paths as $path)
{
    $currentNode = &$tree;

    $parts = explode(">>>", $path);

    foreach ($parts as $part)
    {
         $node = explode("~", $part);

         // create all nodes along this path
         if (!isset($currentNode[$node[0]]))
         {
              $currentNode[$node[0]] = array(
                "ID"            => $node[0],
                "NAME"          => $node[1],
                "DESCRIPTION"   => $node[2],
                "CHILDREN"      => array(),
              );
         }

         $currentNode = &$currentNode[$node[0]]["CHILDREN"];
    }
}

var_dump($tree);
产出:

array
  1 => 
    array
      'ID' => string '1' (length=1)
      'NAME' => string 'root' (length=4)
      'DESCRIPTION' => string 'the root node' (length=13)
      'CHILDREN' => 
        array
          2 => 
            array
              'ID' => string '2' (length=1)
              'NAME' => string 'category1' (length=9)
              'DESCRIPTION' => string 'First category' (length=14)
              'CHILDREN' => 
                array
                  4 => 
                    array
                      'ID' => string '4' (length=1)
                      'NAME' => string 'subCatOfCategory1' (length=17)
                      'DESCRIPTION' => string 'SubCategory of Cat 1' (length=20)
                      'CHILDREN' => &
                        array
                          empty
          3 => 
            array
              'ID' => string '3' (length=1)
              'NAME' => string 'category2' (length=9)
              'DESCRIPTION' => string 'Second category' (length=15)
              'CHILDREN' => 
                array
                  empty
循环将创建包含在路径中的所有节点,因此,如果同时插入
1~根~根节点>>>2~类别1~第一类
,则无需插入
1~根~根节点

如果节点是路径的最后一个节点,则只能通过创建节点来更改此设置。路径的长度是
count($parts)
,您可以计算内部foreach循环中的级别


我希望这就是你想要的。

Phew,一个巨大的问题!我有一种感觉,它可以被压缩成几个段落,让读者更容易理解,取而代之的是代码(包括第85行)。不同的方法是:在插入子树时使用注释引用,而不是变量(
$$treeRootPattern
)。如果必须使用诸如
$foo[“bar”]
之类的字符串访问变量,则不能使用
eval
。请参阅以解释错误消息:
$fullTree[1]['CHILDREN']
不是有效的变量名。只有
$fullTree
是名称,其余部分稍后由PHP解释
$fullTree[1]['CHILDREN']
读作:访问数组$fullTree。转到索引
1
指向的内存。将其解释为数组。转到索引
子项所指向的内存。因此,从一开始就没有名为
$fullTree[1]['CHILDREN']
的变量,因此您无法通过变量访问它。:-)谢谢巴斯蒂,现在说得通了--
array
  1 => 
    array
      'ID' => string '1' (length=1)
      'NAME' => string 'root' (length=4)
      'DESCRIPTION' => string 'the root node' (length=13)
      'CHILDREN' => 
        array
          2 => 
            array
              'ID' => string '2' (length=1)
              'NAME' => string 'category1' (length=9)
              'DESCRIPTION' => string 'First category' (length=14)
              'CHILDREN' => 
                array
                  4 => 
                    array
                      'ID' => string '4' (length=1)
                      'NAME' => string 'subCatOfCategory1' (length=17)
                      'DESCRIPTION' => string 'SubCategory of Cat 1' (length=20)
                      'CHILDREN' => &
                        array
                          empty
          3 => 
            array
              'ID' => string '3' (length=1)
              'NAME' => string 'category2' (length=9)
              'DESCRIPTION' => string 'Second category' (length=15)
              'CHILDREN' => 
                array
                  empty