How to create a navigation menu by using recursion and multidimensional arrays

recursive clock

Throughout this article we shall be talking about how to use recursion and multidimensional arrays for building the structure of a navigation menu.

This is what you get

If you want to see now the final result of this article, please click here to open a new tab with the output of the script that we shall be writing.

I don't know any page on the Internet without a navigation menu. Do you? Even the simplest web page you can imagine has one. It's so common that we tend to forget how important it is for our site. I'm sure that it would be strange to you not to find one when browsing a web page.

Although you can hardcode a navigation menu, what happens if you don't even know how many items the navigation menu will contain or how they will be placed. If that's your case, then you will have to build the structure of the menu by retrieving the information from a database.

The database

Although you could use your favourite RDBMS, in this article we shall be using MYSQL and phpMyAdmin to handle the model of our application.

We're going to create a database and a table with five fields ('item_id', 'parent_id', 'item', 'link' and 'weight'). You can see the details in the following image:

Structure of the MYSQL table

Every single list item has an item_id and parent_id attribute. The trick is that if the list item is a sub-item, then its parent_id will be the item_id of the item from which it hangs. If a list item is not a sub-item, then its parent_id will be 0. These list items would match those at the top of the navigation menu or, in other words, they would be, in a tree-like structure, the offshoots at the bottom of the tree. Please, take a look at the following image:

details of the MYSQL table

Since Apple and Toshiba have a parent_id of 0, they will be placed at the top level of the navigation menu. Likewise, Iphone, iPod, iPad and Mac will fall under Apple as they have a parent_id of 1, which is the item_id of Apple. Note that the field weight is used to order the list items that are found on the same level. For example, if we wanted to make iPad the first list item, then we would have to assign it a value less than zero (for instance, -1).

The programming

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Print Menu</title>
</head>

<body>
<h3>Print Menu</h3>
<?php

/**
 * File name: print_menu.php
 * File Version: 1.0
 * Written by: Jesús Heredia Reboira
 * What does this script do?
 *   This little script prints out the structure of a navigation menu by
 *   using a recursive function. The list items are retrieved from a DB and
 *   stored in a multidimensional array.
 */

/**
 * This recursive function prints out the structure of a navigation menu.
 *
 * @param array $parent_element
 *   This is the first element of the multidimensional array
 *   that is used to store the list items. It matches those list items
 *   at the top of the navigation menu.
 */
function printMenu($parent_element) {

  // This is the array that contains all the list items.
  global $items;

  // We start an unordered list.
  echo '<ul>';

  // We loop through each sub-array.
  foreach ($parent_element as $item_id => $list_item) {

    // We display the item.
    echo '<li>' . $list_item;

    // Now we have to check for sub-items.
    if (isset($items[$item_id])) {

      // If TRUE, then this function calls itself (recursive function)
      // in order to create the structure of the navigation menu.
      printMenu($items[$item_id]);

    }

    // We complete the list item.
    echo '</li>';

  } // End of foreach().

  // We close the unordered list.
  echo '</ul>';

}

// Link to the database.
$dbc = @mysqli_connect('host', 'username', 'password', 'database') OR die('<p>There was an error when
connecting to the database.</p>');

// This query retrieves and orders all the list items.
$query = 'SELECT * FROM table ORDER BY parent_id, weight ASC';

$request = mysqli_query($dbc, $query);

// This array will store the list items that are retrieved from the database.
$items = array();

while (list($item_id, $parent_id, $item, $link) = mysqli_fetch_array($request, MYSQLI_NUM)) {

  if ($link == '') {

    $items[$parent_id][$item_id] = $item;

  } else {

    $item_link = '<a href="' . $link . '">' . $item . '</a>';

    $items[$parent_id][$item_id] = $item_link;

  }

}

// We print out the content of the array for debugging.
echo '<pre>' . print_r($items, 1) . '</pre>';

// We send the first array element to the printMenu() function.
printMenu($items[0]);
?>
</body>
</html>

Once the navigation menu is printed out, it's time to give it some style. This task is up to you. There are dozens upon dozens of ways you could style a navigation menu. If you're planning to style a navigation menu for being used on mobile devices, this might be a good choice for you.