• Hi there

    I’m trying to add a function in my functions.php of my childtheme to switch between to different side-navigations.

    If a user is logged in I want to display a special menu in my sidebar (set as widget in the backend).
    If he’s logged out I only want to display a login link.

    I registered a second menu location:

    function register_my_menu() {
      register_nav_menu( 'sidebar-menu', __( 'Private Menu' ) );
    }
    add_action( 'init', 'register_my_menu' );

    And now I am trying to switch the menu:

    function my_wp_nav_menu_args( $args = '' ) {
    
    if( is_user_logged_in() ) {
        $args['theme_location'] = 'sidebar-menu';
        $args['menu'] = 'private-menu';
    } else {
        $args['theme_location'] = 'sidebar-menu';
        $args['menu'] = 'login-menu';
    }
        return $args;
    }
    add_filter( 'wp_nav_menu_args', 'my_wp_nav_menu_args' );

    Unfortunately this does not work. It actually also switches my primary menu.
    Is there any way how to target only my menu at my sidebar theme location?

    PS: I did create those two menus in the admin area. The two names are the menu’s slugs.
    And I cannot use any plugins.

    Thanks for any hint on that subject…

Viewing 6 replies - 1 through 6 (of 6 total)
  • As you’ve seen, the filter runs every time wp_nav_menu() gets called, so your best bet is to check the location before substituting in your menu:

    if ( 'sidebar-menu' === $args['theme_location'] && is_user_logged_in() ) {
      $args['menu'] = 'private-menu';
    }
    
    /* nothing gets changed if we're not looking at the sidebar menu area */
    return $args;
    Thread Starter nr2012

    (@nr2012)

    Thank u very much for your help in the first place.
    Sounds definitely logic, what you are saying. The thing is, that I had to make a custom menu in my sidebar (widget).

    https://postimg.org/image/a35yn9fvb/

    I realized now, that this of course has another theme_location than the one I invented (and which is not called anywhere).

    So I either would have to know which theme_location custom sidebar widget menus have, or I tried the following:

    function my_wp_nav_menu_args( $args = '' ) {
        if ( $args['menu'] === 'login-menu' && is_user_logged_in() ) {
            $args['menu'] = 'private-menu';
        }
    
        return $args;
    }
    
    add_filter( 'wp_nav_menu_args', 'my_wp_nav_menu_args' );

    Which would just change it if a user is logged in.
    Unfortunately this does not work, I don’t know why, but it does not…


    I just tried some other things.
    I printed out all the $args of each menu and I saw the following:
    [slug] => login-menu

    So I thought this code should work:

    function my_wp_nav_menu_args( $args = '' ) {
    
        if ( $args['slug'] == 'login-menu' && is_user_logged_in() ) {
            $args['menu'] = 'private-menu';
        }
    
        return $args;
    }
    
    add_filter( 'wp_nav_menu_args', 'my_wp_nav_menu_args' );

    Somehow it does not either…

    Despite the counter-intuitiveness of this code, it actually works. This code will only affect navigation menus generated by the default “Custom Menu” widget.

    if ( ! empty( $args['menu'] ) && is_user_logged_in() ) {
      $args['menu'] = 'private-menu';
    }

    Unfortunately, I have to leave soon, but I’ll post a bit more explanation when I get back.

    Thread Starter nr2012

    (@nr2012)

    I got it to work with this:

    if ( $args['theme_location'] == '' && is_user_logged_in() ) {
            $args['menu'] = 'private-menu';
        }

    but maybe your’s is cleaner. I’m looking forward to your explanation. Thanks in advance.
    Could you maybe say one or two words about the reason, why my ‘slug’-variant did not work?
    cheers

    One thing about both of our code is that it affects all of the Custom Menu widgets, do if you’ve placed multiple widgets, they’ll all be changed. I couldn’t figure out how to deal with that.

    The oddity here is that if you do a var_dump( $args ) in your function, you’ll get slightly different output. When you call wp_nav_menu() directly, the key menu is an empty string. But when the widget generates the menu, the key menu contains a PHP object that contains the arguments and some other interesting data. So if menu is empty, you’re not looking at the widget. (As you discovered, if theme_location is empty, you are looking at the widget.) That’s also why your slug variant didn’t work; technically, $args doesn’t contain slug, $args['menu'] does. This would have worked:

    if ( $args['menu']->slug === 'login-menu' && is_user_logged_in() ) {
      $args['menu'] = 'private-menu';
    }
    Thread Starter nr2012

    (@nr2012)

    That’s true. In my case it’s no big deal if it affects all custom menus.
    And now thanks to your explanation I understand also the slug-case.
    I was already wondering, why slug was on my page but not in de documentation of wordpress. But this explains it.
    Thanks for taking the time and explaining things in great detail.
    Very much appreciated.
    Have a nice day

    cheers

Viewing 6 replies - 1 through 6 (of 6 total)
  • The topic ‘Swap menus in sidebar if user is logged in or logged out’ is closed to new replies.