WordPress 3 comes with integrated menu management. Although still a bit quirky at times, it makes creating and managing (navigation) menus a breeze. However, now that creating and displaying a menu takes nothing more than one line of code (wp_nav_menu), we appear to have lost the ability to “manually” add our own stuff.

For instance, by design, there is no “home” link on any menu. Though it is easy to create a custom menu item in the menu management, there is an easier way, using WordPress filters.

The navigation menu can be “filtered”, and so can the navigation menu items. This allows us to add menu items at will.

Inspired by a support request, I did a bit of digging, the result are the following three code snippets, that you can add to your themes functions.php file and will add a login/logout link, add a search field or a Home Page link to your WordPress 3 navigation menu.

Add a login/logout link to your navigation menu

add_filter('wp_nav_menu_items', 'add_login_logout_link', 10, 2);
function add_login_logout_link($items, $args) {

		ob_start();
		wp_loginout('index.php');
		$loginoutlink = ob_get_contents();
		ob_end_clean();

		$items .= '<li>'. $loginoutlink .'</li>';

	return $items;
}

Explanation:

First we add a function add_login_logout_link to the wp_nav_menu_items filter. Then, the ob_start, ob_get_contents and ob_end_clean (lines 4, 6 and 7) functions are “output Buffering” PHP functions that will “intercept” the information that would otherwise be sent to the browser. wp_loginout('index.php'); will add the logic and html code to login (if not logged in yet), or logout (if logged in). Since we don’t want to send that code to the browser yet, we “capture” the output (using ob_get_contents) in a variable ($searchform), and finally include that variable as a list item in the menu.

Add a search field to your navigation menu

add_filter('wp_nav_menu_items','add_search_box', 10, 2);
function add_search_box($items, $args) {

		ob_start();
		get_search_form();
		$searchform = ob_get_contents();
		ob_end_clean();

		$items .= '<li>' . $searchform . '</li>';

	return $items;
}

Create your own searchform template

The add_search_box function will include the default searchform in the menu bar. This however may not be the desired layout (perhaps it contains preceding text “search:” and a “search” button), so you should create a template file searchform.php in your theme template directory, and add the following code:

<form method="get" class="search-form" id="search-form" action="<?php bloginfo( 'home' ); ?>/">

	<div class="formfield">
		<input class="formInputText" type="text" name="s" id="search-text" value="Search ..." size="12" maxlength="16" tabindex="1" onfocus="if (this.value == 'Search ...') {this.value = '';}" onblur="if (this.value == '') {this.value = 'Search ...';}" />
	</div>
	
</form>

Optionally, you can add styling to your form to match your navigation style, using (for example!):

input.formInputText {
	margin-top: 7px;
	color: #666;
	padding: 3px;
	background: #ccc;
}

input.formInputText:hover {
    cursor: help;
    color: 555;
    background: #ccc;
}

Add a Home Page link to your navigation menu

add_filter( 'wp_nav_menu_items', 'add_home_link', 10, 2 );
function add_home_link($items, $args) {

		if (is_front_page())
			$class = 'class="current_page_item"';
		else
			$class = '';

		$homeMenuItem =
				'<li ' . $class . '>' .
				$args->before .
				'<a href="' . home_url( '/' ) . '" title="Home">' .
				$args->link_before . 'Home' . $args->link_after .
				'</a>' .
				$args->after .
				'</li>';

		$items = $homeMenuItem . $items;

	return $items;
}

props to Division by Zero

Add these to a specific menu only

The filter will run for each menu you have defined, so the samples above will be added to each one of those. This may not always be what you want, so to add the desired code to a specific menu location only, add a condition to the code, to make sure the code only executes for a specific menu location:

function add_login_logout_link($items, $args) {

	if($args->theme_location == 'Primary') {

		ob_start();
		wp_loginout('index.php');
		$loginoutlink = ob_get_contents();
		ob_end_clean();

		$items .= '<li>'. $loginoutlink .'</li>';

	}
	return $items;
}

69 comments

  1. Tom

    Hi, I’m getting error when I add your login and search functions to the funtions.php

    for the login i get the error
    Fatal error: Call to undefined function add_filter() in C:\xampp\htdocs\jameswp\wp-includes\functions.php on line 4304
    that on the 1st line of your code

    and then on the search function I get this error I get the same error

  2. Rick Beckman

    I saw your trick for adding the search form to the nav menu on WPRecipes.com, and noticed right away that it can be simplified a bit.

    The login/out link code may be simplified as well:

    add_filter('wp_nav_menu_items', 'add_login_logout_link', 10, 2);
    function add_login_logout_link($items, $args) {
    $loginoutlink = wp_loginout('index.php', false);
    $items .= '<li>'. $loginoutlink .'</li>';

    return $items;
    }

  3. zeaks

    Thanks for this info. Is there a way to style the loginout link in the menu? I’ve tried .menu-item-logoutlink and variations but I can’t figure it out. I’m also unable to see how to do it through firebug.

  4. zeaks

    With the loginout link in the navigation, is it possible to also show the “Dashboard” link?

  5. […] First we add a function add_login_logout_link to the wp_nav_menu_items filter. Then, the ob_start, ob_get_contents and ob_end_clean (lines 4, 6 and 7) functions are “output Buffering” PHP functions that will “intercept” the information that would otherwise be sent to the browser. wp_loginout('index.php'); will add the logic and html code to login (if not logged in yet), or logout (if logged in). Since we don’t want to send that code to the browser yet, we “capture” the output (using ob_get_contents) in a variable ($searchform), and finally include that variable as a list item in the menu. via VanWeerd […]

  6. Colman Carpenter

    Hi,

    Great article!

    Having a bit of a problem, though, trying to add a login/out link to a specific menu in Headway. Headway doesn’t use standard menu areas (primary, secondary, etc), so I’m trying to identify based on the menu name using the line

    if($args->menu == ‘Account’) {

    I have also tried using the menu id ‘7’

    This isn’t working though 🙁

    Can you help?

    1. Ronald

      remove the conditional code, and try

      add_filter('wp_nav_menu_Account_items', 'add_login_logout_link', 10, 2);

  7. blackbookdesign

    Hi,

    thx for the tips.
    cheers 🙂

  8. yoyo

    hi .. i still don’t understand on how to add homepage link into my navigation menu .. just copy all the codes or i must edit it first ? how about the color codes does it mean same with others or i must edit the blue colors? sorry i’m newbie on this..

  9. Bart

    Hoi Ronald.

    Quick question. Seems like the logout link is being added the every custom menu I create. I only want it to show up in the nav bar. Can the code easily be tweaked for this to be the case?

    Kind regards

    Bart

    1. Ronald

      Hi Bart,

      check the last paragraph of the article, titled: “Add these to a specific menu only”

  10. Bart

    Bit embarrassed here, I didn’t see that part.

    Anyway I tried everything but somehow I am missing something. My main navigation menu is called ‘Main’ so I suppose the code should look like this:


    add_filter('wp_nav_menu_items', 'add_login_logout_link', 10, 2);
    function add_login_logout_link($items, $args) {

    if($args->theme_location == 'Main') {

    ob_start();
    wp_loginout('index.php');
    $loginoutlink = ob_get_contents();
    ob_end_clean();

    $items .= ''. $loginoutlink .'';

    }

    return $items;

    }

    I don’t get an error, I just don’t see the link anymore. Confused here 🙂

    1. Ronald

      Is that the theme location as can be see in wp-dashboard > Appearance > Menus?

  11. Jon

    Thanks the login/out code worked. But what about a register/admin sub-menu to it?

  12. Bronwyn

    HI,

    this is great and works well, but we’d like it to redirect to a specific page on our website e.g. /?page_id=12 instead of redirecting to the default WP login. is this possible?

    many thanks

    1. Ronald

      you don’t need this code for that. Add a custom menu item via wp-dashboard > Appearance > Menus, and specify the target URL

      1. Bronwyn

        We’ve tried that but how do we make the same menu link switch between Logout and Login i.e. when logged in it says Logout and when logged out it says login. There seems to only be one option to set the label?

  13. Carlo

    Hello! I tried to put the 2 functions but in the search form to add the custom appears out of the menu bar, any help?
    my code:
    add_filter(‘wp_nav_menu_items’, ‘add_login_logout_link’, 10, 2);
    function add_login_logout_link($items, $args) {

    ob_start();
    wp_loginout(‘index.php’);
    $loginoutlink = ob_get_contents();
    ob_end_clean();

    $items .= ”. $loginoutlink .”;

    return $items;
    }

    add_filter(‘wp_nav_menu_items’,’add_search_box’, 10, 2);
    function add_search_box($items, $args) {

    ob_start();
    get_search_form();
    $searchform = ob_get_contents();
    ob_end_clean();

    $items .= include(TEMPLATEPATH . ‘/search-form.php’);

    return $items;
    }
    Thanks!

  14. Bbvoncrumb

    Thanks a lot. After much searching a failed results even on the WordPress forums, this worked perfectly.

    Thanks!

  15. Pixel Fish

    I have added the Login/log out code to my functions file and it works perfectly.
    I now need to remove it but even after it has been removed from functions.php, it is still being displayed in the menu.

    How do I remove it?

    1. Ronald

      Probably a caching issue, disable caching plugins, if any, clear the plugins cache and/or clear your browser cache.

  16. jane

    Hoping you can help – I love the code that adds a search bar to the menu, it worked beautifully. However, my theme also is using a menu call function in the sidebar. How can I get the search box to only show up in the top navigation?

    Thanks –

    1. jane

      Should mention also, that the way the designer set up the menus doesn’t seem to utilize the “Primary” “Secondary” theme locations. Those are blank, yet there are still two menus – one called “Main Menu” and the other called “Social.”

      1. jane

        Tried this:

        add_filter('wp_nav_menu_items','add_search_box', 10, 2);
        function add_search_box($items, $args) {

        if($args->theme_location == 'Main Menu') {

        ob_start();
        get_search_form();
        $searchform = ob_get_contents();
        ob_end_clean();

        $items .= '' . $searchform . '';
        }
        return $items;
        }

        But it only removes both search bars. Any suggestions?

      2. Ronald

        Hi,

        the code relies on the wp_nav_menu function, using the menu locations.

        Removing another search box is unrelated to this code, and can be done by either editing the theme template files, or use css to hide the search form.

  17. Bill

    Hey there!

    First off, these are very useful. Unfortunately.. it didn’t come out as I thought it would on my site and kinda ruined my theme. I fixed that though, had backups and whatnots. But now I have a problem with removing this search box off of the header menu.

    Care to shed any light on this? Thanks a lot =]

  18. Michele

    Hi,
    I am using twenty twelve with a child theme. I have a link in my primary nav menu where I have an link for “My Account” which has a sub menu with a “Login/Register” link that redirects to a modified wp-login.php. Is it possible for me to turn the “Login/Register” link into a “Logout” link when a user is logged in? If it is possible, would you know how I could accomplish this, or point me in the right direction?

    I have been searching for quite some time with no luck. I would like to leave the menu intact since the sub menu will have more links added to it.

    Thank you

  19. Alex

    Why don’t you create plugins for this options/features and publish them on wordpress.org/plugin ?

  20. Karen Vance

    So I love the dynamic Login and Logout function code you provided. Thank you for the great tips.

    I’m wondering though if there’s a way to make it initiate the CSS class “popup” that is available inside my WordPress theme?

    For example, click “Returning Customer / Login” and you can see that a pop-up box opens. This is thanks to a Custom Link – /#LoginPopup with the CSS class of “popup” inside the WP-Admin for Menus.

    Is there a way to have your function with the dynamic Login/Logout trigger the Popup instead of sending you to the /wp-admin login page?

    Thank you for your insights and thoughts,
    Karen

    P.S. The Theme is Vellum Parrallelus (http://themeforest.net/item/vellum-responsive-wordpress-theme/full_screen_preview/6914246)

Leave a Reply