PHP递归菜单功能

时间:2013-10-25 22:28:13

标签: php recursion multidimensional-array menu

我对这篇文章的情况非常相似

PHP: nested menu with a recursive function, expand only some nodes (not all the tree)

我需要一些帮助...

以下是我的$ menuJSONArray变量的(部分)内容(在调用函数时使用):

    Array
(
[0] => Array
    (
        [Menu_IDX] => 1
        [Order] => 1
        [Name] => History
        [Parent] => 
        [Path] => History
        [Link] => 
    )

[1] => Array
    (
        [Menu_IDX] => 2
        [Order] => 25
        [Name] => Review
        [Parent] => 
        [Path] => Review
        [Link] => Review
    )

[2] => Array
    (
        [Menu_IDX] => 3
        [Order] => 35
        [Name] => Past Medical History
        [Parent] => 
        [Path] => Past Medical History
        [Link] => Past Medical History
    )
 [3] => Array
    (
        [Menu_IDX] => 4
        [Order] => 45
        [Name] => Item 1
        [Parent] => 0
        [Path] => Item 1
        [Link] => Item 1
    )
 [4] => Array
    (
        [Menu_IDX] => 5
        [Order] => 55
        [Name] => Item 2
        [Parent] => 0
        [Path] => Item 2
        [Link] => Item 2
    )
 [5] => Array
    (
        [Menu_IDX] => 6
        [Order] => 65
        [Name] => Item 3
        [Parent] => 0
        [Path] => Item 3
        [Link] => Item 3
    )
)

依旧......

我正在使用下面的功能,但我一直卡在第一项的循环中。真的需要一些帮助包围我的大脑围绕这个功能。提前谢谢大家,这个社区摇滚!!

///RECURSIVE MENU
function recursive($parent, $array) {
$has_children = false; //set value of has children to false by default
foreach($array as $key => $value) {  //loop through the array as key-value pairs
    if ($value['Parent'] == $parent) {  //if the value of Parent field is equal to parent variable   
        if ($has_children === false && $parent) {  //if children is false but parent is not null, this is a sub item
            $has_children = true;  //children is true
            echo '<ul>' ."\n";  //create parent menu ul
        } //otherwise just create the item
        echo '<li>' . "\n";  //create li for parent menu item
        echo '<a href="'.$value['Path'].'">' . $value['Name'] . '</a>' . " \n";  //create link for menu item
            recursive($key, $array); //create sub menu
        echo "</li>\n"; //end parent menu item
    }
}
if ($has_children === true && $parent) echo "</ul>\n"; //end parent menu
}

?>
<?php echo recursive(0, $menuJSONArray); ?></ul>

我得到的回报是:

<ul>



<li>
<a href="History">History</a> 
<li>
<a href="History">History</a> 
<li>
<a href="History">History</a> 
<li>
<a href="History">History</a> 
<li>
<a href="History">History</a> 
<li>
<a href="History">History</a>

似乎无法退出这个循环。谢谢!

P.S。我不关心从引用的帖子中折叠树等,因为我将使用jquery和css处理它。我无法获得菜单语法的正确输出。

2 个答案:

答案 0 :(得分:4)

当我同意@Tim Withers时,我开始解决准备当前数组的问题:

function prepareMenu($array)
{
  $return = array();
  //1
  krsort($array);
  foreach ($array as $k => &$item)
  {
    if (is_numeric($item['Parent']))
    {
      $parent = $item['Parent'];
      if (empty($array[$parent]['Childs']))
      {
        $array[$parent]['Childs'] = array();
      }
      //2
      array_unshift($array[$parent]['Childs'],$item);
      unset($array[$k]);
    }
  }
  //3
  ksort($array);
  return $array;
}

一些解释。

  1. 这是一个弱点,因为我认为菜单数组的顺序是恒定的。假设顺序是:
    • 首要元素
    • 之后的孩子们
    • 在孩子的孩子之后
    • 等......
  2. 这是我在数组开头添加子项以保存原始订单的地方。
  3. 回滚到原始订单。
  4. 然后用于构建菜单:

    function buildMenu($array)
    {
      echo '<ul>';
      foreach ($array as $item)
      {
        echo '<li>';
        echo $item['Name'];
        if (!empty($item['Childs']))
        {
          buildMenu($item['Childs']);
        }
        echo '</li>';
      }
      echo '</ul>';
    }
    

    有了这个正确的数组顺序,无论兔子洞有多深 - 你都有你的树。

    用法:

    $menu = prepareMenu($menu);
    buildMenu($menu);
    

    当然......必须有更好的方式...... :-P


    编辑:

    对于数组(有点中间化[下一个孩子]):

    $menu = array(
    array(
            'Menu_IDX' => '1',
            'Order' => '1',
            'Name' => 'History',
            'Parent' => '',
            'Path' => 'History',
            'Link' => '',
        ),
    array
        (
            'Menu_IDX' => '2',
            'Order' => '25',
            'Name' => 'Review',
            'Parent' => '',
            'Path' => 'Review',
            'Link' => 'Review',
        ),
    array
        (
            'Menu_IDX' => '3',
            'Order' => '35',
            'Name' => 'Past Medical History',
            'Parent' => '',
            'Path' => 'Past Medical History',
            'Link' => 'Past Medical History',
        ),
    array
        (
            'Menu_IDX' => '4',
            'Order' => '45',
            'Name' => 'Item 1',
            'Parent' => '0',
            'Path' => 'Item 1',
            'Link' => 'Item 1',
        ),
    array
        (
            'Menu_IDX' => '5',
            'Order' => '55',
            'Name' => 'Item 2',
            'Parent' => '0',
            'Path' => 'Item 2',
            'Link' => 'Item 2',
        ),
    array
        (
            'Menu_IDX' => '6',
            'Order' => '65',
            'Name' => 'Item 3',
            'Parent' => '0',
            'Path' => 'Item 3',
            'Link' => 'Item 3',
        ),
    array
        (
            'Menu_IDX' => '7',
            'Order' => '65',
            'Name' => 'Item 31',
            'Parent' => '5',
            'Path' => 'Item 31',
            'Link' => 'Item 31',
        )
    );
    

    输出将是:

    • 历史
      • 第1项
      • 第2项
      • 第3项
        • 第31项
      • 评分
      • 过去的病史

答案 1 :(得分:1)

你的问题中有很多细节,那很好。

查看代码,我看到的第一个问题是:

if ($value['Parent'] == $parent) {

第一次进入foreach循环时,$value['Parent']NULL$parent0

由于您正在进行==比较,因此评估结果为TRUE。请尝试改为:

if ($value['Parent'] === $parent) {

请注意===。这也检查数据类型并要求它匹配。

第二个问题将是以下行:

if ($has_children === false && $parent) {  //if children is false but parent is not null, this is a sub item

注释清楚地表明您要检查$parent是否为空,但是您没有这样做,您将整数值$parent转换为布尔值,因此{{ 1}}将被视为0,其他任何内容将被视为FALSE

尝试改为:

TRUE
相关问题