在PHP中递归创建一个多维数组

时间:2009-10-19 21:51:59

标签: php recursion menu multidimensional-array

我试图找出编写PHP函数的最佳方法,该函数将从mysql表中递归地构建具有未知数量的子级别的多维数组。其目的是创建一个数据结构,可以循环创建网站上的导航菜单,每个菜单项可能都有一个带子菜单项的子菜单。

表中的注释字段为:
int ItemID
int ParentID
varchar ItemText
文字ItemLink
tinyint HasChildren

所以函数返回数组的一个例子是:

$menuItems = 
    array(
        itemID# => 
            array(
                'ItemText' => 'Home',
                'ItemLink' => 'index.php',
                'Children' => array(
                        itemID# => array (
                            'ItemText' => 'Home Sub 1',
                            'ItemLink' => 'somepage.php',
                            'Children' => 0
                        ),
                        itemID# => array (
                            'ItemText' => 'Home Sub 2',
                            'ItemLink' => 'somepage2.php',
                            'Children' => 0
                        ),
                    )
            ),
        itemID# => 
            array(
                'ItemText' => 'Contact',
                'ItemLink' => 'contact.php',
                'Children' => 0
            )
        )
    );

如果有人能指出我正确的方向来实现这一点,我将非常感激。谢谢!

4 个答案:

答案 0 :(得分:6)

不太难。您所做的是将菜单项存储在一个数组中,您可以通过ID查找它们。然后迭代菜单项,如果它们具有非null的ParentID,则将它们添加到父项的子项列表中。然后从主列表中删除所有子项,这样您只剩下顶级项目。

代码:

<?php
$menuItems = array
(
    1 => array
    (
        'ItemText' => 'Home',
        'ItemLink' => 'index.php',
        'ParentID' => null,
    ),

    2 => array
    (
        'ItemText' => 'Home Sub 1',
        'ItemLink' => 'somepage.php',
        'ParentID' => 1,
    ),

    3 => array
    (
        'ItemText' => 'Home Sub 2',
        'ItemLink' => 'somepage2.php',
        'ParentID' => 1,
    ),

    4 => array
    (
        'ItemText' => 'Contact',
        'ItemLink' => 'contact.php',
        'ParentID' => null,
    ),
);

// Each node starts with 0 children
foreach ($menuItems as &$menuItem)
    $menuItem['Children'] = array();

// If menu item has ParentID, add it to parent's Children array    
foreach ($menuItems as $ID => &$menuItem)
{
    if ($menuItem['ParentID'] != null)
        $menuItems[$menuItem['ParentID']]['Children'][$ID] = &$menuItem;
}

// Remove children from $menuItems so only top level items remain
foreach (array_keys($menuItems) as $ID)
{
    if ($menuItems[$ID]['ParentID'] != null)
        unset($menuItems[$ID]);
}

print_r($menuItems);
?>

输出:

Array
(
    [1] => Array
        (
            [ItemText] => Home
            [ItemLink] => index.php
            [ParentID] => 
            [Children] => Array
                (
                    [2] => Array
                        (
                            [ItemText] => Home Sub 1
                            [ItemLink] => somepage.php
                            [ParentID] => 1
                            [Children] => Array
                                (
                                )

                        )

                    [3] => Array
                        (
                            [ItemText] => Home Sub 2
                            [ItemLink] => somepage2.php
                            [ParentID] => 1
                            [Children] => Array
                                (
                                )

                        )

                )

        )

    [4] => Array
        (
            [ItemText] => Contact
            [ItemLink] => contact.php
            [ParentID] => 
            [Children] => Array
                (
                )

        )

)

答案 1 :(得分:3)

每次获取数组元素时都有一个自我调用的函数。 如:

调用您的函数以显示节点。然后它检查它的调用节点是否有一个子菜单,如果有,它再次调用自己。并且该过程重复直到它消失,并且所有先前的函数调用都返回。

void printData($mysql_table_node){
    if($mysql_table_node.has_node()){
        for($i = 0; $i < $mysqql_table_node.num_nodes()){
            printData($mysql_table_node->own_node);
        }
    }
        return;
}

答案 2 :(得分:3)

多维树和无序HTML列表生成器

  1. 从多维数组中递归构建
  2. (1)生成多维HTML列表代码。
  3. 您永远不会知道给定项目列表中有多少维度。 每个元素可以有一个儿子 - >孙子 - >大孙子等等。

    因此,您必须使用recursive function 来生成多维列表。

    以下是代码:

    <?php
    
    $categories = array(
        '1'=>   array('name'=>'one','parent'=>null),
        '2'=>   array('name'=>'two','parent'=>null),
        '20'=>  array('name'=>'twenty','parent'=>'2'),
        '21'=>  array('name'=>'twenty one','parent'=>'2'),
        '210'=> array('name'=>'two hundred and ten',    'parent'=>'21'),
        '211'=> array('name'=>'two hundred and eleven', 'parent'=>'21'),
        '212'=> array('name'=>'two hundred and twelve', 'parent'=>'21')
    );
    
    $tree=Menu::CreateTree($categories);
    print_r($tree);
    Menu::GenerateMenuHtmlCode($tree);
    
    class Menu
    {   
        public static function GenerateMenuHtmlCode($tree)
        {
            echo '<ul>';
            foreach ($tree as $key=>$value)
            {
                 echo "<li>".$value['name'];
                 if(!empty($value['sons'])) 
                     self::GenerateMenuHtmlCode($value['sons']);
                 echo "</li>";
            }
            echo '</ul>';
        }
    
        public static function CreateTree($categories)
        {
            $tree=array();
            self::AddElement(&$categories,&$tree,null);
            return $tree;
        }
    
        private function AddElement($categories,&$tree,$parent)
        {
            foreach ($categories as $key=>$value)
            {
                if($value['parent']==$parent)
                {
                    $tree[$key]=$categories[$key];
                    $tree[$key]['sons']=array();
                    self::AddElement($categories,&$tree[$key]['sons'],$key);
                }
                if(empty($tree['sons'])) unset ($tree['sons']);
            }
            unset($categories[$parent]);
            return ;
        }
    }
    ?>
    

    结果:

    Array
    (
        [1] => Array
            (
                [name] => one
                [parent] => 
                [sons] => Array()
            )
    
        [2] => Array
            (
                [name] => two
                [parent] => 
                [sons] => Array
                    (
                        [20] => Array
                            (
                                [name] => twenty
                                [parent] => 2
                                [sons] => Array()
                            )
    
                        [21] => Array
                            (
                                [name] => twenty one
                                [parent] => 2
                                [sons] => Array
                                    (
                                        [210] => Array
                                            (
                                                [name] => two hundred and ten
                                                [parent] => 21
                                                [sons] => Array()
                                            )
    
                                        [211] => Array
                                            (
                                                [name] => two hundred and eleven
                                                [parent] => 21
                                                [sons] => Array()
                                            )
    
                                        [212] => Array
                                            (
                                                [name] => two hundred and twelve
                                                [parent] => 21
                                                [sons] => Array()
                                            )
                                    )
                            )
                    )
            )
    )
    

    <ul>
        <li>one</li>
        <li>two
            <ul>
                <li>twenty</li>
                <li>twenty one
                    <ul>
                        <li>two hundred and ten</li>
                        <li>two hundred and eleven</li>
                        <li>two hundred and twelve</li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
    

    Visit Ilan Roberman website

答案 3 :(得分:2)

我知道这是一个迟到的回复,但我在上面找到了这个脚本,这太棒了。我遇到了一个问题,虽然因为ItemID工作的方式而导致我的孩子不安,当我用一个类似设计的表来运行OP时。为了解决这个问题,并且考虑到大多数Web服务器中的RAM量应该能够处理这个问题,我已经采用了John Kugelman's很好的示例并稍微修改了它。我不是必须将子项应用于所有项目,然后在之后取消设置,而是创建一个新数组并将其全部构建在一个

代码:

$new_array = array();
foreach ($menuItems as $key => &$menuItem) {
    if (($menuItem['ParentID'] != NULL) && ($menuItem['ParentID'] != '')) {
        $new_array[$menuItem['ParentID']]['Children'][$menuItem['ItemID']] = &$menuItem;
    } else {
        $new_array[$menuItem['ItemID']] = &$menuItem;
    }
}

print_r($new_array);

希望这可以帮助别人,因为上面肯定帮助了我