Code Snippet: Add A Link To Latest Post To WordPress Nav Menu

Someone on #wordpress IRC support channel was trying to add link to their latest blog post to their WordPress navigation menu, so I threw together a few lines of code to help them accomplish this.

// Front end only, don't hack on the settings page
if ( ! is_admin() ) {
	// Hook in early to modify the menu
	// This is before the CSS "selected" classes are calculated
	add_filter( 'wp_get_nav_menu_items', 'replace_placeholder_nav_menu_item_with_latest_post', 10, 3 );
}

// Replaces a custom URL placeholder with the URL to the latest post
function replace_placeholder_nav_menu_item_with_latest_post( $items, $menu, $args ) {

	// Loop through the menu items looking for placeholder(s)
	foreach ( $items as $item ) {

		// Is this the placeholder we're looking for?
		if ( '#latestpost' != $item->url )
			continue;

		// Get the latest post
		$latestpost = get_posts( array(
			'numberposts' => 1,
		) );

		if ( empty( $latestpost ) )
			continue;

		// Replace the placeholder with the real URL
		$item->url = get_permalink( $latestpost[0]->ID );
	}

	// Return the modified (or maybe unmodified) menu items array
	return $items;
}

Place the above code in a plugin or just in your theme’s functions.php file.

Create a new “Custom Link” menu item where the URL is #latestpost (which will act as a placeholder and target for the code). You can title the item whatever you please. This code will then find that menu item (by looking for the placeholder URL) and then replace it’s URL with that of the latest post’s URL. Since the filter is before the code that adds the selected CSS classes runs, the menu highlighting will even work. When you visit the latest post on your blog, this menu item will light up.

Rather simple and elegant. You gotta love WordPress hooks.

89 thoughts on “Code Snippet: Add A Link To Latest Post To WordPress Nav Menu

  1. First off, this is a fantastic snippet. Thanks for putting it out there.

    Question: Is it possible to confine this snippet to drawing posts from a particular category?

    • Yes! See this snippet from the code?

              // Get the latest post
              $latestpost = get_posts( array(
                  'numberposts' => 1,
              ) );
      

      Just add the category in there, like so:

              // Get the latest post
              $latestpost = get_posts( array(
                  'numberposts' => 1,
                  'category' => 123,
              ) );
      

      Hope that helps! =)

  2. Code worked perfect the first time in my menu. Thanks!

    Is there a way to use this code to make a link from a button on a page to the most recent category? (Same way it does from the menu) I have been beating my head on my desk trying to figure out a solution on this one…

    • “A button on a page”? Such as in the content of the page? Sounds like you want a shortcode for that.

      add_shortcode( 'latestposturl', 'shortcode_latestposturl' );
      
      function shortcode_latestposturl() {
      
      	// Get the latest post
      	$latestpost = get_posts( array(
      		'numberposts' => 1,
      	) );
      
      	if ( empty( $latestpost ) )
      		return '#';
      
      	return get_permalink( $latestpost[0]->ID );
      }
      • Thanks for this snipped Alex. works great on the menu.

        I’m trying to redirect from the footer links (on a template) to the most recent post of a category, and the previous shortcodes doesn’t work unless it’s in a content page.

        Any idea how to get that working?

        Thanks for your time.

        Alex

      • I use your code for “Custom Link” menu item that links with the placeholder to last post of category id 4. And it’s working fine: (part of the code)

        if ( ‘#latestpost’ != $item->url )
        continue;

        // Get the latest post
        $latestpost = get_posts( array(
        ‘numberposts’ => 1,
        ‘category’ => 4,
        ) );

        What I need is to use another “Custom Link” menu item, That will link to the latest post in category id 5.
        What is the complete code for doing this?

  3. This code is fantastic- what I’d like to know is how to have the 5 latest blog posts instead of just the first. Is that possible?

  4. Thanks Viper, this helped me solve something that I could not fix with a plugin…

    For anyone looking to do this with a custom post type, here’s the part of the code that you need to edit (add the ‘post_type” line):

    $latestpost = get_posts( array(
    ‘numberposts’ => 1,
    ‘post_type’ => ‘your_post_type_here’,
    ) );

    And to lookup all the other arguments that you can pass into the get_posts function, see:
    http://codex.wordpress.org/Function_Reference/get_post

  5. Hello. Thanks for the helpful code. I modified it slightly as suggested in the comments to return the latest 5 entries along with their titles. I would like to truncate long titles though so it works better in my menu. I have tried unsuccessful to modify the script to do so usually other tutorials a reference but it’s clear I don’t really know what I’m doing. Can someone help me out? Here’s what I have

    /* recent blog posts */
    
    /**
     * This is a version of
     * http://www.viper007bond.com/2011/09/20/code-snippet-add-a-link-to-latest-post-to-wordpress-nav-menu/
     * that supports multiple placeholders. In this case, the placeholder fetches
     * the latest post from a particular category.
     */
    // Front end only, don't hack on the settings page
    if ( ! is_admin() ) {
    	// Hook in early to modify the menu
    	// This is before the CSS "selected" classes are calculated
    	add_filter( 'wp_get_nav_menu_items', 'replace_placeholder_nav_menu_item_with_latest_post', 10, 3 );
    }
    // Replaces a custom URL placeholder with the URL to the latest post
    function replace_placeholder_nav_menu_item_with_latest_post( $items, $menu, $args ) {
    	// Loop through the menu items looking for placeholder(s)
    	foreach ( $items as $item ) {
    		$args = array(
    			'numberposts' => 1,
    		);
    		switch ( $item->url ) {
    			case '#latestpost1':
    				$args['offset'] = 0;
    				break;
    			case '#latestpost2':
    				$args['offset'] = 1;
    				break;
    			case '#latestpost3':
    				$args['offset'] = 2;
    				break;
    			case '#latestpost4':
    				$args['offset'] = 3;
    				break;
    				
    			case '#latestpost5':
    				$args['offset'] = 4;
    				break;
    			// Not one of our placeholders
    			default;
    				continue 2;
    		}
    		// Get the latest post
    		$latestpost = get_posts( $args );
    		if ( empty( $latestpost ) )
    			continue;
    			
    	    //shorten title, doesn't work, don't know what i'm doing
    	    /*substr( $title, 0, strpos($title, ' ', 35) );*/
    	    
    		// Replace the placeholder with the real URL
    		$item->url = get_permalink( $latestpost[0]->ID );
    		$item->title = $latestpost[0]->post_title;
    	}
    	
    
    
    	// Return the modified (or maybe unmodified) menu items array
    	return $items;
    }
    
    • Replace this line:

      $item->title = $latestpost[0]->post_title;

      With this:

      $item->title = substr( $latestpost[0]->post_title, 0, strpos( $title, ' ', 35 ) );

      That will cut off the title before the first space found after the first 35 characters are skipped.

      • Thanks for the quick reply. For some reason I was getting an offset error so I just simplified it to

        		$item->title = substr( $latestpost[0]->post_title, 0, 25 );

        Would be nice to add a “…” at the end but I don’t want to get too complicated with ifs. Thanks

  6. Pingback: Adding Dynamic Product Lists To Your WordPress Menu | Chrome Orange

  7. Hi Alex, I am trying to put together something similar, I need a menu item that dynamically links to the most recently added category of a custom taxonomy. Any ideas on how to pull that into the loop?

  8. Hi Trixi, I could manage to do it with a plugin called “Blog in Blog”. It’s pretty straight forward:

    As the documentation explains, use a shortcode in your page (mine e.g = [blog_in_blog category_slug=’brands+case-studies’ num=1 pagination=off] ). This calls the category brands and case studies and shows one post without pagination. Simply add the page ID to your menu.

    Hope this helps! 😉

    Alex

  9. Thanks Alex, this code helped me a lot!

    Now I want to have multiple menu items, all pointing to the latest posts within different categories. How do I duplicate this code in functions.php.

    I want a button for the category ‘Life’, and for ‘Sketches’, and from what I’ve understood, I use ‘category’ => Life,

    But do I duplicate the whole snippet of code multiple times for each category, or is there a better way of doing it?

    Regards,
    Øystein

  10. Thank you for your code, which I found almost usefull to me 🙂 the issue here is that I need to add the latest 11 posts to my menu item number 45. Is it possible with this? Could you help? Thank you.
    Best regards.
    H.

  11. This code worked great exactly what I was looking for… The shortcode example worked great for linking a button.

  12. Any thoughts on the performance implications of doing this with 3 x 4 placeholders pulling posts from 3 categories? I’m thinking adding those 3 extra get_posts() requests is suboptimal. I’m considering caching the data somehow, but that introduces its own complications.

    Anyway, thanks for the inspiration, it’s a great starting point for what I want to do.

  13. Mate – I just want to say thanks so much. Your work is really simple and clever and I love that you’ve given such detailed responses to people’s questions. It really helped me work out how to implement this.
    So, in summary – you’re a legend! Thanks!

  14. This is awesome, I’ve made it a plugin and am using it for links to the first and last post. Is there any possible way to use this technique to put links in the menu for the next post and the previous post? And maybe even a random link?

    • Sure. Just use different placeholders and then the next/previous link functions:

      https://codex.wordpress.org/Function_Reference/get_next_posts_link
      https://codex.wordpress.org/Function_Reference/get_previous_posts_link

      Don’t forget to remove the menu item when is_single() returns false though, i.e. those functions won’t work when viewing your homepage.

      Random would just be 'orderby' => 'rand' on the get_posts() call but be warned, this will murder your database trying to do this as it’s a super slow and resource intensive query as it has to fetch all posts and then sort them.

      • Unfortunately my PHP understanding is just good enough to get myself into trouble. I tried this change before I asked you and I got a link to nothing.

          
         // Get the latest post
                $latestpost = get_previous_posts_link( array(
                    'post_type'      => 'Buttermilk',
                    'numberposts' => 1,
                ) );
        

        I am unsure how to go about removing the menu item when is_single returns false. Any help would be awesome. Also, I just moved to Eugene from Portland, small world…Go Sounders!

          • So like this? This results in bringing me to the first post…Sorry if I am asking for too much!

            // Loop through the menu items looking for placeholder(s)
            foreach ( $items as $item ) {

            // Is this the placeholder we’re looking for?
            if ( ‘#lastpost’ != $item->url )
            continue;

            $item->url = previous_posts( false );

            if ( empty( $latestpost ) )
            continue;

            // Replace the placeholder with the real URL
            $item->url = get_permalink( $latestpost[0]->ID );
            }

  15. Pingback: How to add a "Latest Post" link to my Wordpress nav menu

  16. I had to replace
    $latestpost = get_posts( array(
    ‘numberposts’ => 1,
    ) );

    with:
    $latestpost = get_posts( array(
    ‘posts_per_page’ => 1,
    ) );

    Then, it worked perfectly, thx 😉

    • It’s pretty straight-forward:

      // Front end only, don't hack on the settings page
      if ( ! is_admin() ) {
      	// Hook in early to modify the menu
      	// This is before the CSS "selected" classes are calculated
      	add_filter( 'wp_get_nav_menu_items', 'replace_placeholder_nav_menu_item_with_latest_post', 10, 3 );
      }
      
      // Replaces a custom URL placeholder with the URL to the latest post
      function replace_placeholder_nav_menu_item_with_latest_post( $items, $menu, $args ) {
      
      	// Loop through the menu items looking for placeholder(s)
      	foreach ( $items as $item ) {
      		if ( '#latestpost1' == $item->url ) {
      			$latestpost = get_posts( array(
      				'numberposts' => 1,
      			) );
      		}
      		elseif ( '#latestpost2' == $item->url ) {
      			$latestpost = get_posts( array(
      				'offset'      => 1,
      				'numberposts' => 1,
      			) );
      		}
      		elseif ( '#latestpost3' == $item->url ) {
      			$latestpost = get_posts( array(
      				'offset'      => 2,
      				'numberposts' => 1,
      			) );
      		}
      		else {
      			$latestpost = false;
      		}
      
      		if ( empty( $latestpost ) ) {
      			continue;
      		}
      
      		$item->url = get_permalink( $latestpost[0]->ID );
      	}
      
      	// Return the modified (or maybe unmodified) menu items array
      	return $items;
      }

      Extend from there if you want more. 🙂

      • Ah, thanks Alex,

        I see what I was doing wrong now.

        I neglected to mention that I wanted the different placeholders to be for different categories. So I simply removed the ‘offset’ and added category id (I’m assuming an offset of 2 shows the second most recent post?)

        Thanks!

    • For anyone else with this question, make this change in the code:

      // Get the latest post
      $latestpost = get_posts( array(
      ‘numberposts’ => 1,
      ‘post_type’ => ‘whatever-post-type-you-want-goes-here’,
      ) );

  17. This works perfectly for me in the menu! Is there a way to make this a page or site-wide change? For instance, if I had a button somewhere else that linked to ‘#latestpost’ that wasn’t in my menu, how would I make this function search outside of the menu for ‘#latestpost’ and apply the change?

  18. Pingback: WordPress plugin: insert link to latest post (in category) on your menu | T-machine.org

  19. Pingback: Link Roundup: March 2016 - WPVegas

  20. Pingback: ostatni dodany post w menu - Wordpress Front End Developer

  21. Hi Alex,

    This blog is old, but working, even on latest WP. Nice work man 🙂

    I have one question, maybe you can help. If I want to add a name/title of the blog post besides the URL, is there a way? How could I do that? I want to create dynamic megamenu with latest blog posts from few categories and I would like to fill them out without manual title editing.

    Let me know if you can help.

    Best,
    Marin

  22. Hello, it works very well, but what I want to do is how can we show the latest additions to the relevant category under all categories?

    $categories = get_the_category();
    $category_id = $categories[0]->cat_ID;

  23. Thanks for posting this tip. I did apply it but it doesn’t seem to be working. I just get the domainname/#latestposts url. I also updated the functions.php file. So I’m not sure what I’m doing wrong

Comments are closed.