Updated this to be more flexible. Returns category objects, omitting all empty.
// Gets Categories by Post Type
// returns categories that aren't empty
function get_categories_for_post_type($post_type = 'post', $taxonomy = '') {
$exclude = array();
$args = array(
"taxonomy" => $taxonomy,
);
$categories = get_categories($args);
// Check ALL categories for posts of given post type
foreach ($categories as $category) {
$posts = get_posts(array(
'post_type' => $post_type,
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'field' => 'term_id',
'terms' => $category->term_id
)
)
));
// If no posts in category, add to exclude list
if (empty($posts)) {
$exclude[] = $category->term_id;
}
}
// If exclude list, add to args
if (!empty($exclude)) {
$args['exclude'] = implode(',', $exclude);
}
// List categories
return get_categories($args);
}
add that to your functions.php
To use (for example, if populating a select
for filtering):
<select>
<?php
$categories = get_categories_for_post_type('projects', 'project_categories');
foreach($categories as $category) { ?>
<option value="<?php echo $category->slug; ?>">
<?php echo $category->name; ?>
</option>
<?php } ?>
</select>