How to add nav menu items to a specific position within a menu

I’m adding login/logout links to a nav menu using the following code:

function rp_add_login_logout_links( $items, $args ) {

    $link = wp_loginout( get_permalink( get_option( 'woocommerce_myaccount_page_id' ) ), false );

    if ( 'Shop Menu' == $args->menu ) {
        $items .= '<li id="menu-item-login" class="menu-item menu-item-login">' . $link . '</li>';
    }

    return $items;
}
add_filter( 'wp_nav_menu_items', 'rp_add_login_logout_links', 10, 2 );

Since $items is a string, I can really only easily prepend or append the links to the list. I need this link to appear before a certain menu item in the list, it would end up being the third item from the end. Is there another filter or method I could use to accomplish this?

Read More

I tried using strpos to find the nav item I was looking for and manipulate the $items string but couldn’t get it to match the menu item HTML.

Related posts

1 comment

  1. Turns out there is a wp_nav_menu_objects filter that allows you to modify the array of nav menu items before they are joined into a string. I was able to accomplish what I needed using the following function:

    function wpse121517_add_shop_menu_links( $items, $args ) {
    
        if ( 'Shop Menu' !== $args->menu )
            return $items;
    
        // Where to redirect after logging in or out
        $redirect = get_permalink( get_option( 'woocommerce_myaccount_page_id' ) );
    
        $new_links = array();
    
        if ( is_user_logged_in() ) {
            $label = 'Logout';
            $link = wp_logout_url( $redirect );
    
            // Create a nav_menu_item object to hold our link
            // for My Account, only if user is logged-in
            $item = array(
                'title'            => 'Account',
                'menu_item_parent' => 0,
                'ID'               => 'my-account',
                'db_id'            => '',
                'url'              => get_permalink( get_option( 'woocommerce_myaccount_page_id' ) ),
                'classes'          => array( 'menu-item' )
            );
    
            $new_links[] = (object) $item;  // Add the new menu item to our array
            unset( $item );
        } else {
            $label = 'Login';
            $link = wp_login_url( $redirect );
        }
    
        // Create a nav_menu_item object to hold our link
        // for login/out
        $item = array(
            'title'            => $label,
            'menu_item_parent' => 0,
            'ID'               => 'loginout',
            'db_id'            => '',
            'url'              => $link,
            'classes'          => array( 'menu-item' )
        );
    
        $new_links[] = (object) $item; // Add the new menu item to our array
        $index = count( $items ) - 2;  // Insert before the last two items
    
        // Insert the new links at the appropriate place.
        array_splice( $items, $index, 0, $new_links );
    
        return $items;
    }
    add_filter( 'wp_nav_menu_objects', 'wpse121517_add_shop_menu_links', 10, 2 );
    

Comments are closed.