How do I programatically insert a new menu item?

I’m developing a plugin and I want to insert menu items programmatically.

When my theme creates a menu, it uses this call:

Read More
wp_nav_menu( array( 'theme_location' => 'primary', 'menu_class' => 'nav-menu' ) );

Which resulted in something like this in the HTML:

<div class="nav-menu"><ul>
     <li class="current_page_item"><a href="somewhere">menu-item-1</a></li>
     <li class="page_item page-item-107"><a href="somewhere-else">menu item 2</a></li>
</ul></div>

I want to be able to intercept this somehow and insert my own HTML programmatically before the closing </ul>. How do I hook it up?

Related posts

2 comments

  1. Before being printed, all the menu items get run through a filter. You can target the wp_nav_menu_items filter to tack things on to the menu:

    // Filter wp_nav_menu() to add additional links and other output
    function new_nav_menu_items($items) {
        $homelink = '<li class="home"><a href="' . home_url( '/' ) . '">' . __('Home') . '</a></li>';
        // add the home link to the end of the menu
        $items = $items . $homelink;
        return $items;
    }
    add_filter( 'wp_nav_menu_items', 'new_nav_menu_items' );
    

    Or, to be more specific, you can target only the desired menu by replacing the add_filter line from above with the following, and replacing $menu->slug with your menu’s actual slug name:

    add_filter( 'wp_nav_menu_{$menu->slug}_items', 'new_nav_menu_items' );
    

    Source Tutorial

  2. You can set container to false and use the items_wrap argument to omit the ul, then the function will only output the li tags, letting you wrap it in whatever you need.

    wp_nav_menu(
        array(
            'theme_location' => 'primary',
            'items_wrap' => '%3$s',
            'container' => false
        )
    );
    

Comments are closed.