keaglez

Hi! I'm Jeffri Hong, also known as keaglez, a 21 years old geek who love the web and comic.

Filter get_terms to return only terms with published post

Posted on Programming, Wordpress and tagged with ,

So you are using custom taxonomy. You add terms to the taxonomy, and add the terms to your posts. Then, you use get_terms and list all your terms. Everything works fine, terms that doesn’t have any posts will not be returned if you set hide_empty argument to true. Now you move some of your posts to draft and you get a problem. Terms that doesn’t have any published posts still returned. This lead to 404 error when you click on the link of this term. It doesn’t look good now, we need to remove term that doesn’t have any published post.

So how to do that? The answer is by using WordPress filter. This piece of code below will solve the problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function get_terms_filter( $terms, $taxonomies, $args )
{
	global $wpdb;
	$taxonomy = $taxonomies[0];
	if ( ! is_array($terms) && count($terms) < 1 )
		return $terms;
	$filtered_terms = array();
	foreach ( $terms as $term )
	{
		$result = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts p JOIN $wpdb->term_relationships rl ON p.ID = rl.object_id WHERE rl.term_taxonomy_id = $term->term_id AND p.post_status = 'publish' LIMIT 1");
		if ( intval($result) > 0 )
			$filtered_terms[] = $term;
	}
	return $filtered_terms;
}
add_filter('get_terms', 'get_terms_filter', 10, 3);

The code work like this. We add a filter to the get_terms hook. This hook is called before the terms is returned, so it is perfect to place the filter here. Next, we check each returned terms and see if they have any published post, by using our own query. Why didn’t I use the WordPress WP_Query instead? The answer is I can’t get it to work, beside, it builds a pretty complicated query that might increase your WordPress site load time if it is used too much. Using our own query, we make sure it only use the query that we need. If our query returned that the term has a published post, we add this term to our new array which we use to store the filtered terms. Finally, we return the filtered terms.

Now, when you are using get_terms, you will filter out all terms that doesn’t have any published post. :)

Hope that helps. I have a hard time to explain the situation, so let me know if it doesn’t clear.

Thank you.

If you like this article, share it
  • Digg
  • Facebook
  • Twitter
  • Google Bookmarks
  • del.icio.us
  • MySpace
  • Yahoo! Buzz
  • Reddit
  • StumbleUpon
  • Mixx

2 comments | Leave a comment

  1. Paul January 14, 2011 01:02

    Thanks for this – it’s helped me solve this very problem. However, it wasn’t quite right as it was filtering too aggressively and not showing all the tags in my taxonomy. I tracked down why, and have updated the SQL query to work as follows:

    $result = $wpdb->get_var(“SELECT COUNT(*) FROM $wpdb->posts p, $wpdb->term_relationships rl, $wpdb->term_taxonomy wpt WHERE p.ID = rl.object_id AND rl.term_taxonomy_id = wpt.term_taxonomy_id AND wpt.term_id = $term->term_id AND p.post_status = ‘publish’ LIMIT 1″);

    This isn’t a perfect solution, as it works on the admin area too, so hides any tags which you might have added but haven’t been used in published posts. I might continue to have a crack at it, but have a solution for my needs just now.

    • keaglez January 14, 2011 01:54

      Hi Paul,

      To not filter it on admin area, you can use is_admin() function to check if you are in admin area or not. In this way, you can make sure to not do any filter in the admin area.

Leave a comment

Proudly powered by Wordpress