Twitter Bootstrap Infinite Menu in PHP

What is an Infinite Menu?

It’s a menu than can continue down multiple levels without end in site. Truthfully it’s not infinite since it would never process and your connection would time out or the server would crash. Anyway, I’ve tweaked a recursive function created by this guy, to include classes for the Twitter Bootstrap navbar.

A brief description of what you need for this Infinite Menu…

Basically I created this for my Laravel project. So when I do a database query I get an array of objects. This is our table to sift through and create the menu in the proper order with necessary classes for Twitter Bootstrap to make the navbar. Example:

Array
{
Object(id => 1, name => Home, parent_menu_id => 0),
Object(id => 2, name => Products, parent_menu_id => 0),
Object(id => 3, name => Pants, parent_menu_id => 2),
Object(id => 4, name => Apparel, parent_menu_id => 2),
}

Everything with a parent_menu_id of 0 will be shown all the time the other will be in the child layer of the matching id. It’s easier if you just see the demo.

And below is the function… And finally, the source…
(
P.S. A simple thanks would be nice if it helped. Enjoy!)

global $menuItems;
global $parentMenuIds;
//create an array of parent_menu_ids to search through and find out if the current items have an children
foreach($menu_items as $parentId)
{
  $parentMenuIds[] = $parentId->parent_menu_id;
}
//assign the menu items to the global array to use in the function
$menuItems = $menu_items;

//recursive function that prints categories as a nested html unorderd list
function generate_menu($parent)
{
  $has_childs = false;

  //this prevents printing 'ul' if we don't have subcategories for this category
  global $menuItems;
  global $parentMenuIds;
  //use global array variable instead of a local variable to lower stack memory requierment
  foreach($menuItems as $key => $value)
  {
    if ($value->parent_menu_id == $parent)
    {
      //if this is the first child print '<ul>'
      if ($has_childs === false)
      {
        //don't print '<ul>' multiple times
        $has_childs = true;
        if($parent != 0)
        {
          echo '<ul class="dropdown-menu">';
        }
      }

      if($value->parent_menu_id == 0 && in_array($value->id, $parentMenuIds))
      {
        echo '<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">' . $value->name . '<b class="caret"></b></a>';
      }
      else if($value->parent_menu_id != 0 && in_array($value->id, $parentMenuIds))
      {
        echo '<li class="dropdown-submenu"><a href="#">' . $value->name . '</a>';
      }
      else
      {
        echo '<li><a href="#">' . $value->name . '</a>';
      }
      generate_menu($value->id);

      //call function again to generate nested list for subcategories belonging to this category
      echo '</li>';
    }
  }
  if ($has_childs === true) echo '</ul>';
}
generate_menu(0);

I’m your typical 24 year old guy who loves technology. I have a Computer Programmer Analyst diploma and am in my 3rd year of a Bachelor of Computer Science degree while working full-time as a programmer. I have experience in multiple programming languages, content management systems, frameworks, and markup languages including but not limited to; Javascript, CSS, HTML, Coldfusion, PHP, C, C++, C#, Java, Pythin, Codeigniter, Laravel, Sharepoint 2010, WordPress, Drupal, and I’m sure there’s a few more I’m forgetting to mention.

Tagged with: , , , , ,
Posted in HTML/CSS, Javascript, PHP, Tips, Twitter Bootstrap, Web Development
15 comments on “Twitter Bootstrap Infinite Menu in PHP
  1. Staci says:

    As requested – thank you! I adapted this a bit and am using it in my CMS. You saved me a ton of time. Thanks for sharing!

  2. Tegar says:

    Hi, thanks for providing this function.
    Anyway, could you remake the function to become more parameter-based instead of global variable based?

  3. Celio says:

    how to assemble the array with a mysql query!
    Than you

    • Hey Celio,

      I would suggest using mysql_fetch_assoc() and use some such as:

      while($row = mysql_fetch_assoc($menuItems))
      {
      }

      instead of the foreach($menuItems as $key => $value)

      Which would then force you to change values such as $value->id to $row[‘id’] since you’re now parsing an associative array instead of an array of objects. If it’s not urgent I may be able to help you further. Let me know.

  4. Webrunner says:

    Hello and thanks for this great function! How would you change the function if the database returned also a number for ordering the children of the same parent (example for Apparel before Pants)? Would we need to add this number in the array fields and rework the function, or just use the number during the query to order the array fields?

    I mean, would we need to also put the order in the generated objects
    Object(id => 3, name => Pants, parent_menu_id => 2, order => 20),
    Object(id => 4, name => Apparel, parent_menu_id => 2, order => 10),

    Or just order the generated objects while creating the array
    Object(id => 4, name => Apparel, parent_menu_id => 2),
    Object(id => 3, name => Pants, parent_menu_id => 2),

    • Hey Webrunner,

      What I’ve done in the past is created a column in the menu items table called display order where each item with the same parent id have a unique sequence of 1, 2, etc.. Example

      id: 1 – parent_menu_id: 0 – name: Home – display_order: 1
      id: 2 – parent_menu_id: 0 – name: Products – display_order: 2
      id: 3 – parent_menu_id: 2 – name: Pants – display_order: 2
      id: 4 – parent_menu_id: 2 – name: Apparel – display_order: 1

      Use your query to order the results by parent_menu_id then display_order and the function should take care of the rest.

      SELECT * FROM menuItems ORDER BY parent_menu_id, display_order

      Hope this helps.

  5. Marcio says:

    Hello Kyle, please, how can I do to get the data from a mysql table? Could you make a version of mysql? Help many people. Thank you.

  6. Suat Korkmaz says:

    This works perfectly! Thank you very much!!!

  7. JOHAAANNS says:

    Hi !

    Sorry for my poor english, i’m french.

    How to work this code :

    function MenuBoostrap($parent,$NoBoucle,$CnxMbreId,$CnxAdminId)
    {
    $html =”;
    global $CnxMbreId;
    global $CnxAdminId;

    if ($NoBoucle ==0)
    {

    $html.= ‘

    Autoformation

    Accueil‘;
    }

    $has_childs = false;

    global $menuItems;
    global $parentMenuIds;

    foreach($menuItems as $key => $value)
    {

    if ($value[‘menu_parent_id’] == $parent)
    {
    if ($has_childs === false)
    {
    $has_childs = true;
    if($parent != 0)
    {
    $html.= ”;
    }
    }

    if($value[‘menu_parent_id’] == 0 && in_array($value[‘menu_id’], $parentMenuIds))
    {

    $html.= ‘‘ . $value[‘menu_nom’] . ‘‘;
    }
    else if($value[‘menu_parent_id’] != 0 && in_array($value[‘menu_id’], $parentMenuIds))
    {
    $html.= ‘‘ . $value->menu_nom . ‘‘;
    }
    else
    {
    $html.= ‘‘ . $value[‘menu_nom’] . ‘‘;
    }
    MenuBoostrap($value[‘menu_id’],1,$CnxMbreId,$CnxAdminId);

    $html.= ”;
    }
    }
    if ($has_childs === true) echo ”;

    if ($NoBoucle ==0)
    {
    if ($CnxMbreId == true and $CnxAdminId == true)
    {
    /***Barre de recherche autocomplete**/
    $html.= ‘

    ‘;
    }
    else
    {
    /***Formulaire connexion membre ***/
    $html.= ‘

    Valider

    ‘;

    }

    $html.= ”;
    /**/
    }
    return $html;
    }

    Only -> return $html !

    With this example, the submenu doesn’t work !
    Please help !
    thx !

  8. Damian says:

    Thanks Kyle. Was getting a little stuck and this helped out a great deal.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

%d bloggers like this: