简体   繁体   English

PHP递归菜单功能

[英]PHP Recursive menu function

I have a very similar situation to this post 我的情况与此相似

PHP: nested menu with a recursive function, expand only some nodes (not all the tree) PHP:具有递归功能的嵌套菜单,仅扩展某些节点(并非所有树)

and I need some help... 我需要一些帮助...

Here is the (partial) contents of my $menuJSONArray variable (used when calling the function): 这是我的$ 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
    )
)

and so on... 等等...

I am using the function below but I keep getting stuck in the loop at the first item. 我正在使用下面的函数,但是在第一项中我一直陷于循环中。 Really need some help wrapping my brain around this function. 确实需要一些帮助使我的脑筋围绕此功能。 Thank you all ahead of time, this community rocks!! 提前谢谢大家,这个社区动摇了!!

///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>

What I get in return is: 我得到的回报是:

<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>

Can't seem to get out of this loop. 似乎无法摆脱这种循环。 Thanks!! 谢谢!!

PS I am not concerned with the collapsing of the tree etc. from the referenced post as I will be handling that with jquery and css. PS我不关心树的崩溃等从引用的职位,因为我将使用jQuery和CSS处理。 I just cannot get the proper output of the menu syntax. 我只是无法获得菜单语法的正确输出。

As I agree with @Tim Withers I start to solve problem from preparing current array: 正如我同意@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;
}

Some explanation. 一些解释。

  1. This is a weak point as I assumed that order of your menu array will be constant. 这是我的弱点,因为我认为菜单数组的顺序将是恒定的。 Assumed order is: 假定的顺序是:
    • top elements first 顶级元素优先
    • after that children 之后那个孩子
    • after that children of children 之后的孩子的孩子
    • so on.. 等等..
  2. Here is a place where I add a child at beginning of array to save original order. 在这里,我在数组的开头添加了一个子级以保存原始顺序。
  3. Rollback to original order. 回滚到原始订单。

Then function to build menu: 然后建立菜单功能:

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>';
}

With this and proper array order, no matter how deep rabbit hole is - you have your tree. 通过这种适当的排列顺序,无论兔子洞有多深,您都可以拥有自己的树。

Usage: 用法:

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

Of course... There must be better way... :-P 当然...一定有更好的方法... :-P


EDIT: 编辑:

For array (a little midification [next child]): 对于数组(有点中间[下一个孩子]):

$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',
    )
);

Output will be: 输出将是:

  • History 历史
    • Item 1 项目1
    • Item 2 项目2
    • Item 3 项目3
      • Item 31 项目31
    • Review 评论
    • Past Medical History 既往病史

Plenty of detail in your question, that's great. 您的问题中有很多细节,这很棒。

Looking at the code, the first issue I see is with the line: 查看代码,我看到的第一个问题是该行:

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

The first time you enter the foreach loop, $value['Parent'] is NULL , and $parent is 0 . 第一次进入foreach循环时, $value['Parent']NULL ,而$parent0

Because you are doing a == comparison, this evaluates to TRUE . 因为您正在进行==比较,所以计算结果为TRUE Try instead: 请尝试:

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

Note the === . 注意=== This also checks the data type and requires it to match as well. 这还将检查数据类型,并要求它也匹配。

The second issue will then be with the line: 第二个问题将是:

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

The comment makes it clear that you want to check that $parent is not null, but you aren't doing that, you are casting the integer value of $parent to a Boolean, so 0 will be treated as FALSE , and anything else as TRUE . 该注释清楚表明,您要检查$parent不为null,但您没有这样做,您正在将$parent的整数值转换为布尔值,因此0将被视为FALSE ,而其他将被视为TRUE

Try instead: 请尝试:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM