admin管理员组

文章数量:1026989

I have three custom post types set up, articles, videos and photos.
I am using standard categories for these post types, and sharing the categories across all post types.

I am trying to create a nav menu for each post type, listing the categories, that should follow the following structure:

  • Photos

    • Cat 1
    • Cat 3
    • Cat 5
  • Videos

    • Cat 2
    • Cat 3
    • Cat 5
  • Articles

    • Cat 1
    • Cat 2
    • Cat 4

Categories that do not contain the custom post type should be hidden.

get_categories() with hide_empty set to 1 is obviously close, but it doesn't allow you to specify a post type.

I have three custom post types set up, articles, videos and photos.
I am using standard categories for these post types, and sharing the categories across all post types.

I am trying to create a nav menu for each post type, listing the categories, that should follow the following structure:

  • Photos

    • Cat 1
    • Cat 3
    • Cat 5
  • Videos

    • Cat 2
    • Cat 3
    • Cat 5
  • Articles

    • Cat 1
    • Cat 2
    • Cat 4

Categories that do not contain the custom post type should be hidden.

get_categories() with hide_empty set to 1 is obviously close, but it doesn't allow you to specify a post type.

Share Improve this question edited Feb 15, 2014 at 13:44 tfrommen 9,2317 gold badges40 silver badges59 bronze badges asked Apr 19, 2013 at 12:44 kdevkdev 8632 gold badges10 silver badges19 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 6

Put the following in your functions.php:

function wp_list_categories_for_post_type($post_type, $args = '') {
    $exclude = array();

    // Check ALL categories for posts of given post type
    foreach (get_categories() as $category) {
        $posts = get_posts(array('post_type' => $post_type, 'category' => $category->cat_ID));

        // If no posts found, ...
        if (empty($posts))
            // ...add category to exclude list
            $exclude[] = $category->cat_ID;
    }

    // Set up args
    if (! empty($exclude)) {
        $args .= ('' === $args) ? '' : '&';
        $args .= 'exclude='.implode(',', $exclude);
    }

    // List categories
    wp_list_categories($args);
}

Now you can call wp_list_categories_for_post_type('photos'); or wp_list_categories_for_post_type('videos', 'order=DESC&title_li=Cats'); and the like.

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>

function for category by post. copy in function.php

function get_categories_by_post_type($post_type, $args = '') {
    $exclude = array();
    //check all categories and exclude
    foreach (get_categories($args) as $category) {
        $posts = get_posts(array('post_type' => $post_type, 'category' => $category->cat_ID));
        if (empty($posts)) { $exclude[] = $category->cat_ID; }
    }
    //re-evaluate args
    if (!empty($exclude)) {
        if(is_string($args)) {
            $args .= ('' === $args) ? '' : '&';
            $args .= 'exclude='.implode(',', $exclude);
        } else {
            $args['exclude'] = $exclude;
        }
    }
    return get_categories($args);
}

I have three custom post types set up, articles, videos and photos.
I am using standard categories for these post types, and sharing the categories across all post types.

I am trying to create a nav menu for each post type, listing the categories, that should follow the following structure:

  • Photos

    • Cat 1
    • Cat 3
    • Cat 5
  • Videos

    • Cat 2
    • Cat 3
    • Cat 5
  • Articles

    • Cat 1
    • Cat 2
    • Cat 4

Categories that do not contain the custom post type should be hidden.

get_categories() with hide_empty set to 1 is obviously close, but it doesn't allow you to specify a post type.

I have three custom post types set up, articles, videos and photos.
I am using standard categories for these post types, and sharing the categories across all post types.

I am trying to create a nav menu for each post type, listing the categories, that should follow the following structure:

  • Photos

    • Cat 1
    • Cat 3
    • Cat 5
  • Videos

    • Cat 2
    • Cat 3
    • Cat 5
  • Articles

    • Cat 1
    • Cat 2
    • Cat 4

Categories that do not contain the custom post type should be hidden.

get_categories() with hide_empty set to 1 is obviously close, but it doesn't allow you to specify a post type.

Share Improve this question edited Feb 15, 2014 at 13:44 tfrommen 9,2317 gold badges40 silver badges59 bronze badges asked Apr 19, 2013 at 12:44 kdevkdev 8632 gold badges10 silver badges19 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 6

Put the following in your functions.php:

function wp_list_categories_for_post_type($post_type, $args = '') {
    $exclude = array();

    // Check ALL categories for posts of given post type
    foreach (get_categories() as $category) {
        $posts = get_posts(array('post_type' => $post_type, 'category' => $category->cat_ID));

        // If no posts found, ...
        if (empty($posts))
            // ...add category to exclude list
            $exclude[] = $category->cat_ID;
    }

    // Set up args
    if (! empty($exclude)) {
        $args .= ('' === $args) ? '' : '&';
        $args .= 'exclude='.implode(',', $exclude);
    }

    // List categories
    wp_list_categories($args);
}

Now you can call wp_list_categories_for_post_type('photos'); or wp_list_categories_for_post_type('videos', 'order=DESC&title_li=Cats'); and the like.

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>

function for category by post. copy in function.php

function get_categories_by_post_type($post_type, $args = '') {
    $exclude = array();
    //check all categories and exclude
    foreach (get_categories($args) as $category) {
        $posts = get_posts(array('post_type' => $post_type, 'category' => $category->cat_ID));
        if (empty($posts)) { $exclude[] = $category->cat_ID; }
    }
    //re-evaluate args
    if (!empty($exclude)) {
        if(is_string($args)) {
            $args .= ('' === $args) ? '' : '&';
            $args .= 'exclude='.implode(',', $exclude);
        } else {
            $args['exclude'] = $exclude;
        }
    }
    return get_categories($args);
}

本文标签: Only list categories that contain posts of a specific custom post type