Create a WordPress menu with many levels without using the walker class or wp_nav_menu from scratch

SPOILER: it works nicely only if you have a two levels menu

Here’s my problem. My goal is to build a WordPress menu from scratch, without the support of the walker class or the classic WordPress menu.

I was able to build a nice one, but if I add one level more than the other two my menu is going to break. Also, I’m having some hard time to add the third level items

I took inspiration from the WordPress documentation, using a menu call: clean_custom_menu().

Here’s my code:

function clean_custom_menu( $theme_location ) {
if ( ($theme_location) && ($locations = get_nav_menu_locations()) && isset($locations[$theme_location]) ) {

$uri = trim($_SERVER[‘REQUEST_URI’], ‘/’);

$menu = get_term( $locations[$theme_location], ‘nav_menu’ );
$menu_items = wp_get_nav_menu_items($menu->term_id);
$menu_list = ‘<nav>’ .”n”;
$menu_list .= ‘<ul class=”main-menu”>’ .”n”;

$count = 0;
$submenu = false;
$subsubmenu =false;

foreach( $menu_items as $menu_item ) {

$link = $menu_item->url;
$title = $menu_item->title;
$clean = preg_replace(‘/[^A-Za-z0-9-]+/’, ‘-‘, $menu_item->title);
$slug = strtolower($clean);

if ( !$menu_item->menu_item_parent ) {
$parent_id = $menu_item->ID;

$menu_list .= ‘<li class=”dropdown”>’ .”n”;
if ($uri == $slug) {
$menu_list .= ‘<a id=”‘.$slug.'” href=”‘.$link.'” class=”btn dropdown-toggle current”>’.$title.'</a>’ .”n”;
} else {
$menu_list .= ‘<a id=”‘.$slug.'” href=”‘.$link.'” class=”btn dropdown-toggle”>’.$title.'</a>’ .”n”;
}

}

if ( $parent_id == $menu_item->menu_item_parent ) {
$nephews = $menu_item->ID;
if ( !$submenu ) {
$submenu = true;
$menu_list .= ‘<div class=”dropdown-menu”>’ .”n”;
}

$menu_list .= ‘<div class=”dropdown-item”>’ .”n”;
$menu_list .= ‘<a href=”‘.$link.'” class=”title”>’.$title.'</a>’ .”n”;
$menu_list .= ‘</div>’ .”n”;

if ( $menu_items[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ){
$menu_list .= ‘</div>’ .”n”;
$submenu = false;
}

}

if ( $parent_id == $menu_item->menu_item_parent && $nephews == $menu_item->menu_item_parent) {

if ( !$subsubmenu ) {
$subsubmenu = true;
$menu_list .= ‘<ul class=”sub-dropdown-menu”>’ .”n”;
}

$menu_list .= ‘<li>’ .”n”;
$menu_list .= ‘<a href=”‘.$link.'” class=”dropdown-item”>’.$title.'</a>’ .”n”;
$menu_list .= ‘</li>’ .”n”;

if ( $menu_items[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ){
$menu_list .= ‘</div>’ .”n”;
$subsubmenu = false;
}

}

if ( $menu_items[ $count + 1 ]->menu_item_parent != $parent_id ) {
$menu_list .= ‘</li>’ .”n”;
$submenu = false;
}

$count++;
}

$menu_list .= ‘</ul>’ .”n”;
$menu_list .= ‘</nav>’ .”n”;

} else {
$menu_list = ‘<!– no menu defined in location “‘.$theme_location.'” –>’;
}

echo $menu_list;
}

As you can notice, I added a nice function to highlight the current item, if the page that you browse is that one that matches with the item.

To call the menu in the header, the only thing that everyone needs to do is to call the menu like that:

Where primary is the name of the menu location.

Can anyone help me in debugging it?

Read more here:: Create a WordPress menu with many levels without using the walker class or wp_nav_menu from scratch

Leave a Reply

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