• Resolved sublimeology

    (@sublimeology)


    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 ALL the same categories (either they belong to all of them or they shouldn’t be displayed).

    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.

    https://pastebin.com/49rFZXZU

    Both parts of the code work as coded but I need to combine the two so when it queries the posts in the second part of the code, the ones selected match ALL categories that the post was in (which are being echo’d in the first bit of code to see if would actually give me the terms).

    Right now, the second part of the code is returning results that are in any of the categories that the post is in – so, it may be in a top level category (and thus, not really related) but still be returned. I need it to return posts that are filed with ALL the categories/terms that the current post has. 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).

Viewing 4 replies - 1 through 4 (of 4 total)
  • Moderator keesiemeijer

    (@keesiemeijer)

    Have you tried the operator ‘AND’:

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

    https://codex.www.ads-software.com/Function_Reference/WP_Query#Taxonomy_Parameters

    Thread Starter sublimeology

    (@sublimeology)

    yes, using the and operator, it shows all the regular posts in that category – not just the custom post types that contain those terms.

    I need it to display only posts that are in the “program_listings” custom post type that match ALL categories of current post.

    I’ve tried pulling the function out of the top part of the code (that is simply echoing the terms right now) into the bottom part of the code (that is displaying posts) but still can’t get it to work.

    I feel like maybe I should be able to do something like this:

    (starting at line 34):

    if ($related_items->have_posts()) :
     foreach($category_terms as $term){
     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>

    In my head, this should tell it to find related posts, match it with the $category_terms, and the display the list. But, that gives me a parse error.

    Thread Starter sublimeology

    (@sublimeology)

    So, I’ve got the code to display posts from each of the relevant categories but I can’t seem to figure out that last step to get it to show only the custom posts from ALL the relevant categories (one list).

    Here’s the new code (still with the troubleshooting term list at the top):

    <!-- other posts -->
       <?php
         //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
    ?>
     <?php
    //for a given post type, return all
    $category_terms = wp_get_object_terms($post->ID, 'category');
    $post_type = 'program_listings';
    $tax = 'category';
    $tax_terms = wp_get_object_terms($post->ID, 'category');
    if ($tax_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,
          'caller_get_posts'=> 1
    
        );
    
        $my_query = null;
        $my_query = new WP_Query($args);
                if( $my_query->have_posts() ) {
          echo '<h2>Other programs in the '. $tax_term->name. ' category</h2> ';
          while ($my_query->have_posts()) : $my_query->the_post(); ?>
            <p><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></p>
            <?php
          endwhile;
        }
        wp_reset_query();
      }
    }
    
    ?>
    
    <!-- end other posts -->
    Thread Starter sublimeology

    (@sublimeology)

    So, I have it working. Basically, the terms are a hierarchical list. So, in order to match all the terms/categories, I really just needed a query to find the last “category” it was in (the final child of the hierarchy), and make it only pull the custom posts from that category (with the right CPT).

    JUST IN CASE anyone else is wanting to do something similar, I thought I would post the code here. I’ve commented areas to see what I was doing in the various places to make it a little more understandable.

    <!-- other posts -->
    <?php
    //this gets the lowest hierarchical child term for 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
    $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 -->

    Hope that helps someone else – this was something that I found alot of questions about how to do but not very many answers.

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘Displaying related posts that match all categories of current post’ is closed to new replies.