The following works, but with the following caveats. It will run for every menu, but it will not run for wp_page_menu
, a usuall default callback if a menu can’t be found.
Finally, menu items aren’t necessary pages – so you may want to do some logic to check that the menu item you are dealing with is a page/post from which you want to obtain the metadata.
Here’s the code:
add_filter( 'wp_setup_nav_menu_item','my_item_setup' );
function my_item_setup($item) {
//Use the following to conduct logic;
$object_id = (int) $item->object_id; //object ID.
$object_type = $item->type; //E.g. 'post_type'
$object_type_label = $item->type_label; //E.g. 'post' or 'page';
//You could, optionally add classes to the menu item.
$item_class = $item->classes;
//Make sure $item_class is an array.
//Alter the class:
$item->classes= $item_class;
//Alter the title:
$pack_meta_value = get_post_meta($object_id, 'test', true );
if($pack_meta_value ){
$item->title = $item->title.'<span>' . $pack_meta_value . '</span>';
}
return $item;
}
I would be interested to see if there was a better way of doing this, preferably a method which allowed you to check for which menu these items are for…
I’ve moved this from the comments. If you wish to restrict this function to a particular menu, you could try the following. This has not been tested.
First remove the add_filter
from the code above. Instead insert into a function which is added onto an earlier hook, and conditionally adds the filter (say when the menu is ‘primary’):
add_filter( 'wp_nav_menu_args','add_my_setup_function' );
function add_my_setup_function($args) {
if( $args['theme_location'] == 'primary' ):
add_filter( 'wp_setup_nav_menu_item','my_item_setup' );
endif;
return $args;
}
Finally remove the filter, once the items have been loaded, so that it isn’t called for secondary menus:
add_filter('wp_nav_menu_items','remove_my_setup_function', 10, 2);
function remove_my_setup_function( $nav, $args ) {
remove_filter( 'wp_setup_nav_menu_item', 'my_item_setup' );
return $nav;
}