Dynamically exclude empty terms from nav menus

Last week a user on WordPress StackExchange inquired about excluding categories from a nav menu on they fly if the category contained no posts. I was able to provide a very simple solution using the wp_get_nav_menu_items action filter and the global $wpdb object [codex]. Today we will expand on this solution slightly to remove empty terms from any taxonomy.

The wp_get_nav_menu_items action filter is applied to the array of menu items in the wp_get_nav_menu_items() function [codex]  and our filter function will receive three arguments, although we’re only going to make use of the first:

  1. $items – the array of menu items
  2. $menu – the menu object
  3. $args – the arguments passed to the wp_get_nav_menu_items() function

First, we’ll access the $wpdb global, which allows us to perform a direct SQL query, and use the get_col method to retrieve an array containing IDs of all empty terms in the database. Then we’ll loop through all of the menu $items and if the menu item is a taxonomy term and the term ID is in the list of empty terms, we’ll remove it.

add_filter( 'wp_get_nav_menu_items', 'gowp_nav_remove_empty_terms', 10, 3 );
function gowp_nav_remove_empty_terms ( $items, $menu, $args ) {
	global $wpdb;
	$empty = $wpdb->get_col( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE count = 0" );
	foreach ( $items as $key => $item ) {
		if ( ( 'taxonomy' == $item->type ) && ( in_array( $item->object_id, $empty ) ) ) {
			unset( $items[$key] );
		}
	}
	return $items;
}