PHP Recursive menu function

前端 未结 2 1625
陌清茗
陌清茗 2020-12-11 13:22

I have a very similar situation to this post

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

and I need some help...

相关标签:
2条回答
  • 2020-12-11 13:51

    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.

    Because you are doing a == comparison, this evaluates to 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.

    Try instead:

    if ($has_children === false && !is_null($parent)) {  //if children is false but parent is not null, this is a sub item.
    
    0 讨论(0)
  • 2020-12-11 13:52

    As I agree with @Tim Withers I start to solve problem from preparing current array:

    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


    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
      • Item 2
      • Item 3
        • Item 31
      • Review
      • Past Medical History
    0 讨论(0)
提交回复
热议问题