PHP: nested menu with a recursive function, expand

2020-02-06 16:38发布

问题:

I have this array, called $nested (it's a long one, but I tried to get a comprehensive scenario):

Array
(
    [1] => Array
        (
            [id] => 1
            [parent] => 0
            [title] => Page 1
        )

    [2] => Array
        (
            [id] => 2
            [parent] => 0
            [title] => Page 2
        )

    [3] => Array
        (
            [id] => 3
            [parent] => 0
            [title] => Page 3
        )

    [4] => Array
        (
            [id] => 4
            [parent] => 0
            [title] => Page 4
        )

    [5] => Array
        (
            [id] => 5
            [parent] => 0
            [title] => Page 5
        )

    [6] => Array
        (
            [id] => 6
            [parent] => 1
            [title] => Page 1-1
        )

    [7] => Array
        (
            [id] => 7
            [parent] => 1
            [title] => Page 1-2
        )

    [8] => Array
        (
            [id] => 8
            [parent] => 1
            [title] => Page 1-3
        )

    [9] => Array
        (
            [id] => 9
            [parent] => 2
            [title] => Page 2-1
        )

    [10] => Array
        (
            [id] => 10
            [parent] => 2
            [title] => Page 2-2
        )

    [11] => Array
        (
            [id] => 11
            [parent] => 2
            [title] => Page 2-3
        )

    [12] => Array
        (
            [id] => 12
            [parent] => 3
            [title] => Page 3-1
        )

    [13] => Array
        (
            [id] => 13
            [parent] => 3
            [title] => Page 3-2
        )

    [14] => Array
        (
            [id] => 14
            [parent] => 4
            [title] => Page 4-1
        )

    [15] => Array
        (
            [id] => 15
            [parent] => 6
            [title] => Page 1-1-1
        )

    [16] => Array
        (
            [id] => 16
            [parent] => 6
            [title] => Page 1-1-2
        )

    [17] => Array
        (
            [id] => 17
            [parent] => 6
            [title] => Page 1-1-3
        )

    [18] => Array
        (
            [id] => 18
            [parent] => 7
            [title] => Page 1-2-1
        )

    [19] => Array
        (
            [id] => 19
            [parent] => 7
            [title] => Page 1-2-2
        )

    [20] => Array
        (
            [id] => 20
            [parent] => 7
            [title] => Page 1-2-3
        )

    [21] => Array
        (
            [id] => 21
            [parent] => 9
            [title] => Page 2-1-1
        )

    [22] => Array
        (
            [id] => 22
            [parent] => 9
            [title] => Page 2-1-2
        )

    [23] => Array
        (
            [id] => 23
            [parent] => 9
            [title] => Page 2-1-3
        )

)

With this recursive function:

function recursive($parent, $array) {
    $has_children = false;
    foreach($array as $key => $value) {
        if ($value['parent'] == $parent) {       
            if ($has_children === false && $parent) {
                $has_children = true;
                echo '<ul>' ."\n";
            }
            echo '<li>' . "\n";
                echo '<a href="/page.php?id=' . $value['id'] . '">' . $value['title'] . '</a>' . " \n";
            echo "\n";
                recursive($key, $array);
            echo "</li>\n";
        }
    }
    if ($has_children === true && $parent) echo "</ul>\n";
}

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

I easily get this output:

  • Page 1
    • Page 1-1
      • Page 1-1-1
      • Page 1-1-2
      • Page 1-1-3
    • Page 1-2
      • Page 1-2-1
      • Page 1-2-2
      • Page 1-2-3
    • Page 1-3
  • Page 2
    • Page 2-1
      • Page 2-1-1
      • Page 2-1-2
      • Page 2-1-3
    • Page 2-2
    • Page 2-3
  • Page 3
    • Page 3-1
    • Page 3-2
  • Page 4
    • Page 4-1
  • Page 5

So far so good.

Now, I would like NOT to show the whole tree at once, but going deeper when the user clicks on a page/subpage, like this:

URL: http://www.example.com/page.php, initial state ("expand" all items with parent = 0)

  • Page 1
  • Page 2
  • Page 3
  • Page 4
  • Page 5

URL: http://www.example.com/page.php?id=1 (expand all items with parent = 1)

  • Page 1
    • Page 1-1
    • Page 1-2
    • Page 1-3
  • Page 2
  • Page 3
  • Page 4
  • Page 5

URL: http://www.example.com/page.php?id=6 (expand all items with parent = 6)

  • Page 1
    • Page 1-1
      • Page 1-1-1
      • Page 1-1-2
      • Page 1-1-3
    • Page 1-2
    • Page 1-3
  • Page 2
  • Page 3
  • Page 4
  • Page 5

And so on

Seems a mission impossible to me, any help, please? Thanks in advance

回答1:

You're almost there. Just one small problem: instead of recursive($key, $array) you need recursive($key + 1, $array). Still, as said by others, this would be a lot nicer if you just generated the entire output with PHP and then controlled it all with javascript. Having the page reload every time the user clicks an item is really not a good user experience.



回答2:

At last that's what I did, it works very fine:

// create array of ancestors' ID from current page
function path($page = 0) {
    global $database_connApp, $connApp;
    // let's create arrays
    do {
        mysql_select_db($database_connApp, $connApp);
        $query_rsPage = "SELECT pages.pag_id FROM pages WHERE pages.pag_id = " . $page;
        $rsPage = mysql_query($query_rsPage, $connApp) or die(mysql_error());
        $row_rsPage = mysql_fetch_assoc($rsPage);
        $bid[] = $row_rsPage['pag_id'];
        $page = $row_rsPage['pag_parent'];
    } while ($page > 0);

    // move to the last array index
    end($bid);
    $output = $bid;
    return $output;
}

// create the menu
function fmenu($parent, $array, $path) {
    $has_children = false;
    foreach($array as $key => $value) {
        if (in_array($value['parent'], $path)) {
            if ($value['parent'] == $parent) {
                if ($has_children === false && $parent) {
                    $has_children = true;
                    echo '<ul>' ."\n";
                }
                $active = ($_GET['iData'] == $value['id']) ? ' class="active"' : '';
                echo '<li' . $active . '>' . "\n";
                    echo '<a href="../pagine/' . $value['id'] . '/' . slugify($value['title']) . '.htm">' . html($value['title']) . '</a>' . " \n";
                echo "\n";
                    fmenu($key, $array, $path);
                echo "</li>\n";
            }
        }
    }
    if ($has_children === true && $parent) echo "</ul>\n";
}

echo fmenu(0, $nested, path($row_rsEdit['pag_id']));