List All Posts In WordPress Navigation Menu
You may remember that last week, I’ve been dabbling in the world or WordPress navigation manus hacking around and looking into how to get dynamic Custom Post Type Archives in WordPress Menus.
I got directed towards a related and highly interesting question by @topher1kenobe. Couldn’t stop thinking about an easy and viable solution, so decided to go ahead and code it up.
I know WordPress can automatically add pages to a custom menu, but can we have one where it’ll automatically add posts from a custom content type?
The code is completely based on this one here, with a couple of minor changes in the interpretation part of the item filter.
/* take care of the urls */ add_filter( 'wp_get_nav_menu_items', 'cpt_archive_menu_filter', 10, 3 ); function cpt_archive_menu_filter( $items, $menu, $args ) { /* alter the URL for cpt-archive objects */ $menu_order = count($items); /* Offset menu order */ $child_items = array(); foreach ( $items as &$item ) { if ( $item->object != 'cpt-archive' ) continue; $item->url = get_post_type_archive_link( $item->type ); /* retrieve all children */ foreach ( get_posts( 'post_type='.$item->type.'&numberposts=-1' ) as $post ) { /* hydrate with menu-specific information */ $post->menu_item_parent = $item->ID; $post->post_type = 'nav_menu_item'; $post->object = 'custom'; $post->type = 'custom'; $post->menu_order = ++$menu_order; $post->title = $post->post_title; $post->url = get_permalink( $post->ID ); /* add as a child */ $child_items []= $post; } } return array_merge( $items, $child_items ); }
Remember, this routing looks for a menu item with the object
set to “cpt-archive” (no time to change to a newer more appropriate name as this is quick concept code). That’s it. Again, for the rest of the code refer and a thorough explanation of how it works take a look at Custom Post Type Archives in WordPress Menus.
Since posts are fetched dynamically every time they’re always up to date with the current posts set, meaning when a post is removed or added the menu will change accordingly, which is a huge advantage. Performance may decrease a bit, caching with save_post
invalidation should save you time if it becomes an issue.
Even simpler
A more simple solution, where this function can actually be used as a standalone function, without the metaboxes code for the backend can be implemented as well. By creating a simple Custom Link with the Label of “##post##”, for example and then changing the filter to act like so:
/* take care of the urls */ add_filter( 'wp_get_nav_menu_items', 'cpt_archive_menu_filter', 10, 3 ); function cpt_archive_menu_filter( $items, $menu, $args ) { /* alter the URL for cpt-archive objects */ $menu_order = count($items); /* Offset menu order */ $child_items = array(); foreach ( $items as &$item ) { if ( $item->title != '##post##' ) continue; $item->url = '#'; $item->title = 'All Posts'; foreach ( get_posts( 'post_type=post&numberposts=-1' ) as $post ) { $post->menu_item_parent = $item->ID; $post->post_type = 'nav_menu_item'; $post->object = 'custom'; $post->type = 'custom'; $post->menu_order = ++$menu_order; $post->title = $post->post_title; $post->url = get_permalink( $post->ID ); /* add children */ $child_items []= $post; } } return array_merge( $items, $child_items ); }
Generics can be implemented using regular expression matching for the title. The URL can be set using the get_post_type_archive_link
function for post types with archives. This last version of the snippet can be used as a standalone function, just make sure you label your Custom Links appropriately.
Solutions, improvements, ideas, thoughts always welcome. I’m sure there’s a faster way to add all posts as menu items, isn’t there?
hi, i was wondering where does this code go to?
This can be carefully pasted into your theme’s
functions.php
file or wrapped as a tiny plugin.hai i am using wordpress3.4.2 i am trying to display post to menu with your code but it is not working for me (i put code in to esplande theme functions.php)
Hi there, you will have to provide some more information, error messages, particulars, etc. TurnWP_DEBUG to on in wp-config.php.
Hi , thanks for your sharing, this is what I’m looking for 🙂
but I use your Even simpler code, and it shows all my articles in blog, how can I setting if I want to display 10 posts ??
Muki, see that
foreach ( get_posts( 'post_type=post&numberposts=-1' ) as $post )
part? That function gets all the posts for you. Look atget_posts
reference. Hint: if you want to display 10 post changenumberposts
to 10.Thank you for this! Is there a way to a)have the posts collapse and expand when you click on the post-type b) only display posts for certain post-types. Thanks!
Keliot, there certainly is always a way 😉 What have you tried? What didn’t work out?
Great work and thank you ! It works so fine with me but I would like to add posts thumbs near the title of each of sub-menu post ! I know the function
get_the_post_thumbnail( $post->ID );
but It don’t work without anecho
Have you got an idea ?
Thank U again ?
You could try injecting it into the
title
property, like$post->title = get_the_post_thumbnail( $post->ID ) . ' ' .$post->post_title;
, not sure that will work though as there might be escaping in place which will prevent the HTML from rendering properly. See how it goes and get back to me.Thank U ! It works for me ?
Hi, great post and a huge help! I have implemented the function on my site and all seems to work great however I’m struggling to figure out how to order the items alphabetically asc a-z (currently they are pulling through z-a).
Any help would be hugely appreciated.
Thanks!
Glad to hear it still works after all these years. In order to modify how the posts are shown you need to alter the arguments to
get_posts
. https://codex.wordpress.org/Template_Tags/get_posts has all the arguments listed see if that helps.I know this is an older post, but I wanted to give an update since this helped me! I had an issue with an error when Id save the menu in wp admin. “The given object ID is not that of a menu item.” See full explanation and answer here:
https://wordpress.stackexchange.com/questions/296543/list-all-custom-post-types-posts-in-nav-menu-dynamically
The trick is – you must add this at the beginning (immediately inside) of the filter function:
if ( is_admin() ) { return $items; }
Hi, can we display the latest articles of subcategories?
Category -> Subcategory -> Posts
Sure you can. WordPress is so powerful that you can pretty much do anything with enough time, money and patience.
Hi soulseekah, how can I make this work for many CPT not just for one? Is it possible ? Thanks.
Just change the get_posts parameters: https://developer.wordpress.org/reference/classes/wp_query/#parameters
[…] This code is highly inspired from this: https://codeseekah.com/2012/03/05/list-all-posts-in-wordpress-navigation-menu/ […]