Related posts in all categories of current post (custom post types)

A client of mine has custom post types that they set up using a plugin rather than defining them in the functions.php. (So, YARPP for the solution won’t work). In this custom post types, they have various categories. Each post belongs to one or more categories. After each post, they would like to display 5 posts that are in ALL the same categories (could be one or many categories).

So, what I need to do is set up a way to dynamically find all the categories a post belongs to (I’ve done that & have it set up as an echo right now until I work this out), then query to find 5 posts that belong to the exact same categories (either they belong to all of them or they shouldn’t be displayed).

Read More

Here’s the code I’ve come up with – but, I can’t figure out how to “combine them” so it not only gets the terms (categories) but also forces the query to use those terms to filter the 5 “related” programs.

  //get the post's terms (troubleshooting - can be removed once figured out!   
$category_terms = wp_get_object_terms($post->ID, 'category');
if(!empty($category_terms)){
  if(!is_wp_error( $category_terms )){
    echo 'Terms <ul>';
    foreach($category_terms as $term){
      echo '<li><a href="'.get_term_link($term->slug, 'category').'">'.$term->name.'</a></li>'; 
    }
    echo '</ul>';
  }
}  
//get post terms done
    // get the custom post type's taxonomy terms

    $custom_taxterms = wp_get_object_terms( $post->ID,
                'category', array('fields' => 'ids') );
    // arguments
    $args = array(
    'post_type' => 'program_listings',
    'post_status' => 'publish',
    'posts_per_page' => 5, // you may edit this number
    'orderby' => 'rand',
    'tax_query' => array(
        array(
            'taxonomy' => 'category',
            'field' => 'id',
            'terms' => $custom_taxterms
        )
    ),
    'post__not_in' => array ($post->ID),
    );
    $related_items = new WP_Query( $args );
    // loop over query
    if ($related_items->have_posts()) :
    echo '<h2>Other Programs in this category</h2><ul>';
    while ( $related_items->have_posts() ) : $related_items->the_post();
    ?>
        <li style="margin-left:10px;list-style:none;"><a href="<?php the_permalink(); ?>"
                   title="<?php the_title_attribute(); ?>">
            <?php the_title(); ?></a></li>
    <?php
    endwhile;
    echo '</ul>';
    endif;
    // Reset Post Data
    wp_reset_postdata();

So, get the posts terms & echo them (it won’t be an echo when it’s finished – I was doing that to make sure it actually got the categories/terms) works great. It displays every “category” the post is in. But, the second bit displays posts from any of those categories rather than posts that are only in ALL the categories.

Basically, I need to combine the first & second pieces so that the query only returns results of posts that are in ALL categories of the current post. If a post is not in all the same categories (exact match for ALL categories of current post), it should not be returned. (For example, if a post is in the parent “North America” category, but, not any of the other categories that the post is in, it should NOT be returned in the results).

Related posts

2 comments

  1. This is the code that was needed in order to make it show only the posts (that were of a specific custom post type) that matched the same child category (therefore matching all the other categories):

    <!-- other posts -->
    <?php 
    //this gets the lowest hierarchical child term for current post
    $categories = get_the_category($post->ID);
    foreach($categories as $category) :
        $children = get_categories( array ('parent' => $category->term_id ));
        $has_children = count($children);
        if ( $has_children == 0 ) {
        $current_child = $category->name;
        }
    endforeach;
    //this starts the query for the program listings custom post types
    $post_type = 'program_listings';
    $tax = 'category';
    $tax_terms = wp_get_object_terms($post->ID, 'category');
    if ($tax_terms == $category_terms) {
      foreach ($tax_terms  as $tax_term) {
        $args=array(
          'post_type' => $post_type,
          "$tax" => $tax_term->slug,
          'post_status' => 'publish',
          'operator' => 'AND',
          'posts_per_page' => 5,//limits the listing to 5
          'caller_get_posts'=> 1,
          'post__not_in' => array ($post->ID),
          'orderby' => 'ID', //orders by ID, you could also tell it to order by: ‘author’ ‘title’‘name’‘date’ or ‘rand’
    'order' => 'ASC', //tells it the display order should be ascending, DSC would indicate a descending order
    
        );
        $my_query = null;
        $my_query = new WP_Query($args);
            if( $my_query->have_posts() && $tax_term->name == $current_child)//now only display categories the current post is in
             {
          echo '<h2>Other programs in this category</h2><ul>';
          while ($my_query->have_posts() && $tax_term->name==$current_child ) : $my_query->the_post(); ?>
            <li style="margin-left:15px;list-style:none;"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></li>
            <?php
          endwhile;
        }
        wp_reset_query();
      }
    }
    echo '</ul>';
    ?>
    
    <!-- end other posts -->
    
  2. Have you tried adding an 'operator' to your tax_query:

    'tax_query' => array(
        array(
            'taxonomy' => 'category',
            'field' => 'id',
            'terms' => $custom_taxterms,
            'operator' => 'AND'
        )
    ),
    

Comments are closed.