I have a Custom Post Type that uses the default category, the same as the posts, and some other post types in my site. How can I list all non-empty categories from the custom post type?

For instance, if I have categories “Cat 1”, “Cat 2" and “Cat 3” and I have a default post with a category of “Cat 1", and a custom post with categories “Cat 2” and “Cat 3". How would I write a function that would return “Cat 2” and “Cat 3"?

It seems like the get_terms() functions don’t support a post_type argument. Is there a way I can add some other query to a get_terms() function?

I know that it is possible to hide unused terms:

$terms = get_terms( array(
    'taxonomy' => 'category',
    'hide_empty' => true, <-----
) );

However this hides empty for all post types, I'd like to hide empty for just a custom post type.

  • 1
    hide_empty is based on the count column of wp_terms. This count is based on the total number of posts of any post type for that term. The number of posts of each post type is not stored separately for each post type, so you can't do what you're asking for with get_terms(). You would need to write your own query, but it would be very inefficient since you'd essentially need to check every post. You're probably better of registering a second separate taxonomy for your post type. Apr 23 '19 at 9:34

This will end up being a little convoluted since the taxonomy just describes a relationship that may belong to any of the post types, so there's not a direct data link for what you're trying to fetch.

But you could do something like this (untested), which could be a fairly heavy query if you're doing on every page load or something, so maybe consider running it on a cron job and storing it somewhere or something.


    $args = array(
        'post_type' => 'my-post-type',
        'posts_per_page' => -1,

    $fetch = get_posts( $args );
    $cat_r = array();

    // Iterate the posts and get the categories
    foreach( $fetch as $item ) {
        $cats = get_the_terms( $item->ID, 'category' );
        $cat_r[] = $cats;

    // Outputs an array of term objects
    echo '<pre>';
    print_r( $cat_r );
    echo '</pre>';
  • Thanks for the response – I think I might try to create a custom query instead as the overhead for this would be really big. I really appreciate you taking the time to answer though. Thanks.
    – Djave
    Apr 23 '19 at 9:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.