When building a super simple WordPress theme I created a really simple way that you can use Twitter Bootstrap to build the wp_nav_menu.

I’ve played with twitter bootstrap for a while now and I’ve got to say it’s pretty awesome for knocking up some great looking, responsive sites. You can build a really nice and simple site that works on all platforms. So obviously building WordPress sites with Twitter Bootstrap is a good idea right? But what about the menu? Twitter uses some pretty specific markup and styles to build their menus, so how can we use the w_nav_menu function to build our menu and have it look and work like the Twitter Bootstrap one?
Simple, all it takes is one function 🙂

NOTE

Remember to include Twitter Bootstrap. I usually use this great CDN.

Next it’s time to build our function. It’s pretty simple, we’re going to pass in a variable which will be the menu location we want to use. This is set once you have created a menu, and use the dropdown on the left to set the primary menu. So the first thing to to check if a variable has actually been passes, and if it hasn’t then return false.


function build_menu($menu_name)
{
    if( ! $menu_name ) return false;
}

Now we need to get the menu locations and make sure the specified menu actually exists. So within our function we add all the following code:


if( ! $menu_name ) return false;

$menu_locations = get_nav_menu_locations();
if( ! isset( $menu_locations[$menu_name] ) )
    return false;

Excellent, now lets get the wordpress menus as an object so we can get the id of them menu we want to use, then grab that menu as an array which we can loop through. We also need to get the current page url and the site address url so we can compare them with the menu item links and determine which is the current page.


$menu_obj = get_term( $menu_locations[$menu_name], 'nav_menu' );
if( ! $menu_obj )
    return false;

$menu_id = $menu_obj->term_id;

$url = get_permalink( $post->ID );
$homeurl = get_home_url().'/';

$args = array(
    'order'			=> 'ASC',
    'orderby'			=> 'menu_order',
    'post_type'			=> 'nav_menu_item',
    'post_status'		=> 'publish',
    'output'			=> ARRAY_A,
    'output_key'		=> 'menu_order',
    'nopaging'			=> true,
    'update_post_term_cache'	=> false
);

$items = wp_get_nav_menu_items( $menu_id, $args );

if( !count($items) > 0 )
    return false;

You may find that when you’re on the homepage you don’t see the home link as active. Check that the URL when on home exactly matches the “Site Address (URL)” you have in your General Settings.

We’re ready to work with our menu now.
First we’re going to build an array of all child pages, so create a variable called children and set it as an empty array. Then set our incremental variable, and we’re good to start our foreach through the menu items.


$children = array();
$i = 0;
foreach( $items as $parent )
{
    if( $parent->post_status == 'publish' && $parent->menu_item_parent != '0' ) // Is child
    {
        $page_id = $parent->menu_item_parent;
        $children[$page_id][$i]['url'] = $parent->url;
	$children[$page_id][$i]['title'] = $parent->title;
        $i++;
    }
}

Now it’s time to build our new menu. First we loop through the menu array and check for only published pages and top level (parent) pages. Then we are going to check if the page has any children, and if it does we build those items, otherwise just build the top level items. At each stage remembering to check if the item is the current page or homepage.


$menu = ''; 
$menu .= '<ul class="nav">';
foreach( $items as $item ) // Loop through and get top level items
{
    if( $item->post_status == 'publish' && $item->menu_item_parent == '0' ) // Is top level
    {
        if( array_key_exists($item->ID, $children) ) // If has children
        {
            $menu .= '<li class="dropdown">';
            $menu .= '<a href="'.$item->url.'" class="dropdown-toggle" data-toggle="dropdown">'.$item->title.' <b class="caret"></b></a>';
            $menu .= '<ul class="dropdown-menu">';
            foreach( $children[$item->ID] as $child )
            {
                if($url === $item->url)
                {
                    $menu .= '<li class="active"><a href="'.$child['url'].'">'.$child['title'].'</a></li>';
                } else {
                    $menu .= '<li><a href="'.$child['url'].'">'.$child['title'].'</a></li>';
                }
            }
            $menu .= '</ul>';
            $menu .= '</li>';
        } else {
            if($url === $item->url || $homeurl === $item->url)
            {
                $menu .= '<li class="active"><a href="'.$item->url.'">'.$item->title.'</a></li>';
            } else {
                $menu .= '<li><a href="'.$item->url.'">'.$item->title.'</a></li>';	
            }
        }
    }
}
$menu .= '</ul>';

Great! Then simply output the menu you’ve created like so.


echo $menu;

So all of our lovely code together will look like this:


function build_menu($menu_name)
{
    if( ! $menu_name ) return false;

    $menu_locations = get_nav_menu_locations();
    if( ! isset( $menu_locations[$menu_name] ) )
        return false;

    $menu_obj = get_term( $menu_locations[$menu_name], 'nav_menu' );
    if( ! $menu_obj )
        return false;

    $menu_id = $menu_obj->term_id;

    $url = get_permalink( $post->ID );
    $homeurl = get_home_url().'/';

    $args = array(
        'order'			=> 'ASC',
        'orderby'			=> 'menu_order',
        'post_type'			=> 'nav_menu_item',
        'post_status'		=> 'publish',
        'output'			=> ARRAY_A,
        'output_key'		=> 'menu_order',
        'nopaging'			=> true,
        'update_post_term_cache'	=> false
    );

    $items = wp_get_nav_menu_items( $menu_id, $args );

    if( !count($items) > 0 )
        return false;

    $children = array();
    $i = 0;
    foreach( $items as $parent )
    {
        if( $parent->post_status == 'publish' && $parent->menu_item_parent != '0' ) // Is child
        {
            $page_id = $parent->menu_item_parent;
            $children[$page_id][$i]['url'] = $parent->url;
            $children[$page_id][$i]['title'] = $parent->title;
            $i++;
        }
    }

    $menu = ''; 
    $menu .= '<ul class="nav">';
    foreach( $items as $item ) // Loop through and get top level items
    {
        if( $item->post_status == 'publish' && $item->menu_item_parent == '0' ) // Is top level
        {
            if( array_key_exists($item->ID, $children) ) // If has children
            {
                $menu .= '<li class="dropdown">';
                $menu .= '<a href="'.$item->url.'" class="dropdown-toggle" data-toggle="dropdown">'.$item->title.' <b class="caret"></b></a>';
                $menu .= '<ul class="dropdown-menu">';
                foreach( $children[$item->ID] as $child )
                {
                    if($url === $item->url)
                    {
                        $menu .= '<li class="active"><a href="'.$child['url'].'">'.$child['title'].'</a></li>';
                    } else {
                        $menu .= '<li><a href="'.$child['url'].'">'.$child['title'].'</a></li>';
                    }
                }
                $menu .= '</ul>';
                $menu .= '</li>';
            } else {
                if($url === $item->url || $homeurl === $item->url)
                {
                    $menu .= '<li class="active"><a href="'.$item->url.'">'.$item->title.'</a></li>';
                } else {
                    $menu .= '<li><a href="'.$item->url.'">'.$item->title.'</a></li>';	
                }
            }
        }
    }
    $menu .= '</ul>';
    echo $menu;
}

Now doesn’t that look lovely? Ok so the very last step is to use our function. So in your theme, wherever you want to place your menu, just run your new function and pass in the menu location…like so:


build_menu('primary');

If you have any questions, issues or you’ve maybe got a better way of doing this, please leave a comment below.