1

我设置了一个“无限深度”类别系统,该系统存储在数据库中,其中包含三个重要信息:

  • 类别 ID
  • 父类别 ID
  • 节点路径

前两个是不言自明的,但最后一个需要澄清。如果类别是#20,它的父类是#10,而父类的父类是#5,那么NodePath看起来像5:10:20。通过这种方式,我可以递归地找到类别父分支。

我正在寻找一种从数据库中获取每个类别的方法,然后以某种方式对它们进行排序,结果是这样的数组:

array(
   0 => array(
      3 => array(
         7,
         13,
      ),
      5,
   ),
   1 => array(
      6,
      9
   ),
);

本质上,这是从前面描述的结构创建的树层次结构的映射NodePath

我想出了这样的事情:

 $tree = array();

 foreach( $categories as $category )
 {
    // A NodePath Example is "1:7:13:24" where 1 is the root category,
    // 24 is the "leaf" or end node, and the other numbers are sub categories
    // in order.
    $nodes = explode( ":", $category->NodePath );

    $lastNode = &$tree;
    foreach( $nodes as $node )
    {
        // Add New Branch if not Termination
        if( !isset( $lastNode[ $node ] ) && $node != end($nodes) )
            $lastNode[ $node ] = array();

        // Recursive Addressing
        $lastNode = &$lastNode[ $node ];
    }        
 }

这会产生var_dump()树的这个(与我的数据库中的数据匹配):

array (size=3)
  1 => 
    array (size=1)
      4 => null
  2 => 
    array (size=2)
      5 => 
        array (size=1)
          7 => &null
      6 => null
  3 => null

第三个深度向下将终端节点设置为“&null”,而不仅仅是“null”。我怎样才能解决这个问题?

4

2 回答 2

1

它只发生在数组中的最后一项,因此修复它的一种方法是在末尾添加一个 NULL 值,$categories然后使用以下命令将其删除array_filter

$categories = [
    (object)['NodePath' => '1'],
    (object)['NodePath' => '1:4'],
    (object)['NodePath' => '2'],
    (object)['NodePath' => '2:5:7'],
    (object)['NodePath' => '2:6'],
    (object)['NodePath' => '3'],
    (object)['NodePath' => '2:5'],
    (object)['NodePath' => '3:1']
];

$tree = array();
$categories[] = (object)array('NodePath' => NULL);
foreach( $categories as $category ){
   $nodes = explode( ":", $category->NodePath );
   $lastNode = &$tree;
   foreach( $nodes as $node ){
       // Add New Branch if not Termination
       if( !isset( $lastNode[ $node ] ) && $node != end($nodes) ){
           $lastNode[ $node ] = array();
       }
       // Recursive Addressing
       $lastNode = &$lastNode[ $node ];
   }        
}
$tree = array_filter($tree);
var_dump($tree);

&这是在最后一个值之前没有做我所说的转储。我还尝试重新排列类别数组中的元素,并且效果相同。

array(3) { [1]=> array(1) { [4]=> NULL } [2]=> array(2) { [5]=> array(1) { [7]=> NULL } [6]=> NULL } [3]=> array(1) { [1]=> NULL } } 
于 2013-08-14T20:33:01.117 回答
0
<?php


function builTree($categories){
    $tree = array();
    foreach($categories as $category){
        $path = explode( ":", $category->NodePath );
        $lastNode = &$tree;
        for($deep=0;$deep<count($path);$deep++){
             if(!is_array($lastNode[$path[$deep]])) {
                 if($deep==count($path)-1) { $lastNode[$path[$deep]] = null;}
                 else {$lastNode[$path[$deep]] = array(); $lastNode = &$lastNode[$path[$deep]];}
             } else {$lastNode = &$lastNode[$path[$deep]];}
        }
    }
    return $tree;
}


echo "<pre>";
// works with full tree given
$categories = [
    (object)['NodePath' => '1'],
    (object)['NodePath' => '1:4'],
    (object)['NodePath' => '2'],
    (object)['NodePath' => '2:5:7:90:23'],
    (object)['NodePath' => '2:6'],
    (object)['NodePath' => '3'],
    (object)['NodePath' => '2:5'],
    (object)['NodePath' => '3:1']     // even works with loop paths
];
print_r(builTree($categories));


// works even if just leafs are given
$categories = [
(object)['NodePath' => '2:5:7:90:23'],
(object)['NodePath' => '2:5:7:66:21']
];
print_r(builTree($categories));
于 2013-08-14T22:08:06.323 回答