How to add items to WordPress menu from PHP file?

I have a membership site built off of WordPress and I want to create a navigation menu that is the same for all users, except for one tab that says “Your Subscriptions” and that tab will have a dropdown menu that shows what subscriptions the user has, which will be different for each user.

This is a small sample of what I have now :

Read More
if ( wp_emember_is_member_logged_in('19') ) {
    wp_nav_menu( array( 'menu' => 'example1', 'menu_class' => 'sf-menu' ) );

That will check to see if a member has a certain membership level and then input a menu specific to that membership level. The only problem is I have like 20 elseif statements and 20 menus, which is not efficient at all.

Basically, I want to add single tabs to one menu instead of creating tons of different menus. I’m just not sure how to do it. Thanks!

Edited for question.

Related posts

Leave a Reply

5 comments

  1. Hi there I am a little confused with what it is your after exactly, are you basically saying you want to have a menu for all users, and depending on a certain access level change 1 element in the menu??

    If this is the case it looks like you need an ‘if’ statement to figure out (as you have done) if we are on the right access level and customise the menu accordingly. Basically it looks like you need two different arrays to build you menus:

    if ( wp_emember_is_member_logged_in('19') )
    {//this will be show for users with an access level of 19
        $menu = array( 'menu' => 'example1', 'menu_class' => 'sf-menu' )
    }
    else
    {//this will be show for all users except with an access level of 19
        $menu = array( 'menu' => 'example2', 'menu_class' => 'sf-menu-2' );
    }
    
    wp_nav_menu($menu);
    

    You need to configure/set your menus themselves in this part of WP:

    http://YOUR-DOMAIN/wp-admin/nav-menus.php
    

    EDIT

    It looks like you want to write nicer code and potentially not have 20 different if/else statements…. What I would do is this:

    Have a folder with all your custom menus in it as separate PHP files which share the name with the group level for the user… ie

    custommenus/19.php
    custommenus/20.php
    custommenus/21.php
    custommenus/22.php
    

    Then load the correct menu for the access level like:

    //there must be a way for you to grab the user access level
    //for now I will hard code it
    $current_user_access_level = 19;
    
    $custom_menu_path = 'custommenus/'.$current_user_access_level.'.php';
    $default_menu_path = 'custommenus/default.php';
    
    //check to see if the custom menu file exists first
    if(file_exists($custom_menu_path))
    {
        include $custom_menu_path;
    }
    else
    {//then the file exists, load some sort of default file
        include $default_menu_path;
    }
    

    Then whenever you create a new access level all you need to do is add a new file with the same name as the access level to the ‘custommenus’ folder, if the file hasn’t yet been created it will load a default menu!

    Hope this helps 🙂 [PS this is untested]

  2. ok, the best solution for you is to use custom menu’s i hope this suit your needs…
    You can create two menus like this

    in your functions.php:

    add_action( 'init', 'my_custom_menus' );
    function my_custom_menus() {
        register_nav_menus(
            array(
                'loggedin-menu' => __( 'logged in users' ),
                'newmembers-menu' => __( 'new members' )
            )
        );
    }
    

    then…where you you have the current menu – replace this:

    if ( wp_emember_is_member_logged_in('19') ) {
        wp_nav_menu( array( 'menu' => 'example1', 'menu_class' => 'sf-menu' ) );
    

    With this:

    // check if user is logged in
    if ( is_user_logged_in() ) {
        // Logged in.
        wp_nav_menu( array( 'theme_location' => 'loggedin-menu' ) );
    } else {
        // Not logged in.
        wp_nav_menu( array( 'theme_location' => 'newmembers-menu' ) );
    }
    

    Once you did that you can create the menu’s and have a different menu for logged in users and users that aren’t logged in.

    enter image description here

  3. For anyone else interested, I’ve been working with emagdnim to get an easy solution.

    The best one found was using output buffering in the header.php file. In this way, we can render multiple menus using the wp_nav_menu(), but using output buffering we can break it up into pieces, and move those pieces around.

    Here is the significant code (i.e. updated portion) for bottom-menu.php:

    ........
    <?php /* Our navigation menu. */ ?>
    <?php
    
    if(wp_emember_is_member_logged_in()){
        wp_nav_menu( array( 'menu' => 'normal-menu', 'menu_class' => 'sf-menu' ) );
    
    
    
    /** CUSTOM CODE ADDITION **/
    //connect to database
    $link = mysql_connect("localhost", "[USERNAME]", "[PASSWORD]") or die("Oops! Please wait a few seconds and try again");
    //connect to table
    mysql_select_db("[TABLE NAME]") or die(mysql_error());
    //search table
    $result = mysql_query("SELECT * FROM `wp_wp_eMember_membership_tbl` ORDER BY `alias` ASC");
    $array = array();
    //while there are still rows in the table we haven't been to...
    while ($row = mysql_fetch_array($result)){
        //clean up the "alias" so it becomes the name of the menu
        $alias = strtolower(str_replace(' ','-',$row['alias']));
        //now this can be accessed as "$array[X]" to get the name of the menu.
        if ($alias == 'admin'){
            $alias = 'admin-menu';
            }
        $array[$row['id']] = $alias;
        }
    //done is a way to check if anything is found, if not a default menu is loaded
    echo '{BREAK}';
    $done = 0;
    $ids = array_keys($array);
    $info2 =  wp_eMember_get_user_details("more_membership_levels");
    if (strstr($info2,',')){
        $moreMemberLevels = explode(',',$info2);
        }elseif ($info2 != ''){
        $moreMemberLevels[0] = $info2;
        }
    //go through each ID/menu possibility
    for ($i = 0; $i < count($ids); $i++){
        if ((wp_emember_is_member_logged_in($ids[$i])) || ((is_array($moreMemberLevels)) && ((in_array($ids[$i],$moreMemberLevels))))){
            $done++;
            //add the mneu to wp
            /** UNCOMMENT THIS TO IMPLEMENT LOOKUP VERIFICATION BEFORE ADDING A MENU **/
            /*
            echo 'Searching for '.$array[$ids[$i]].'...';
            $res = mysql_query("SELECT * FROM `wp_posts` WHERE `post_type`='nav_menu_item' AND `post_name`='{$array[$ids[$i]]}' LIMIT 1");
            if (mysql_num_rows($res) == 1){*/
            if ($array[$ids[$i]] != 'free'){
                /** UNCOMMENT THIS TO DEBUG **/
                //echo 'Adding '.$array[$ids[$i]].' to menu...<br />';
                wp_nav_menu(array('menu'=>$array[$ids[$i]], 'menu_class'=>'sf-menu'));
                }
            }
        }
    
    echo ' {BREAK}';
    
    /** END CUSTOM CODE ADDITION **/
    
    
    
        }else{
        wp_nav_menu( array( 'menu' => 'normal-visitor-menu', 'menu_class' => 'sf-menu' ) );
        }
    

    and the updated code for header.php (which loads bottom-menu.php)

    ....
    
    <div id="page" class="hfeed">
    <?php /* ======== BOTTOM MENU ======== */
        ob_start();
        get_template_part('bottom','menu');
        $bm = ob_get_clean();
    
        $bm_array = explode('{BREAK}',$bm);
        $bm_Top = $bm_array[0];
        $bm_Move = strip_tags($bm_array[1],'<li><br /><br><font><b><i><u><em><strong><a>');
        $bm_End = $bm_array[2];
    
        $bottomMenu = str_replace('My Menu Item</a></li>', 'My New Menu Item</a>
    <ul class="sub-menu">'.$bm_Move.'</ul>
    </li>',$bm_Top).$bm_End;
        ob_end_clean();
        echo $bottomMenu;
    //echo '*****'.$bm_Move.'*****';
        ?>
        <div id="main">
    

    Additional Information / Summary of Technique

    This method takes one of two general menus and adds elements to it based on what should be loaded for each membership style. The “elements” are full menus created by wp_nav_manu(), but only one item. The names of the menus are also the names of the membership levels but with hyphens instead of spaces and all lowercase. By doing this, we do not need another table linking the seemingly arbitrary membership level ID with the name of the menu – you simply name the menus/memberships based on this system so it knows what to look for.

    Furthermore, each added “menu” is actually a menu with only one, single menu item with the <ul></ul> tags removed so as to nest them into a sub-menu <ul> below the desired parent element.

    After it is all said and done, we were able to use the wp menu system to dynamically display an infinite possibility of sub-menu items based on their membership level(s) and additional membership levels.

  4. If all you need to add is one menu item at the end of the list, then you can hook up to a filter (wp_nav_menu_items) as described here. Then you can append a menu item with your subscription dropdown. Instead of using if statements, you can simply print the level.

    Using this method, you can have a more fine tuned control over what your menu item will say and, if different levels of membership are similiar. ALSO, the switch statement is preferred to endless (if else)’s.

    -Hope that helps

  5. You could merge items from one menu into another using a wp_nav_menu_objects filter.

    You’d need to know the ID of the menu you wanted to merge in, and the ID of the menu item which you wanted the merged items to be a child of. Then you could just get the menu items, set their parent menu item and merge them with the parent menu. E.g.

    add_filter('wp_nav_menu_objects', 'my_wp_nav_menu_objects_filter', 10, 2);
    
    function my_wp_nav_menu_objects_filter($menu_items, $args) {
      $sub_menu_id = 123;
      $sub_menu_parent_item_id = 456;
    
      $sub_menu_items = wp_get_nav_menu_items($sub_menu_id);
    
      foreach ($sub_menu_items as $item) {
        if (!$item->menu_item_parent) {
          $item->menu_item_parent = $sub_menu_parent_item_id;
        }
      }
    
      return array_merge($menu_items, $sub_menu_items);
    }