How Can I use WP_Query to Only Display 1 Post from Custom Post Type if Query Returns Posts with Matching ID in Custom Field

I have searched high and low for a solution and couldn’t find anything; hopefully someone here more skilled than myself can lend a hand.

I have two testimonial videos (from a video custom post type) displayed randomly every time the page loads. There are different clients that have testimonials and in some cases, there are multiple testimonials from the same client.

Read More

I have the query working that randomly displays two videos from the custom post type (while filtering out a category completely). What I’m trying to avoid is loading two testimonial videos from the same client (looks odd to have two of the same thumbnails show) but I’m not sure how to do this. Here the working code that I have so far:

<?php  $loop = new WP_Query(array(
    'post_type' => 'video',
    'posts_per_page' => 2,
    'orderby' => 'rand',
    'tax_query' => array(
        array(
            'taxonomy' => 'video_category',
            'field' => 'slug',
            'terms' => 'assess-core-certification',
            'operator' => 'NOT IN')
        )
    ));
?>

<?php if ( $loop ) : while ( $loop->have_posts() ) : $loop->the_post(); ?>

<div  class="testimonialVideo top">

    <div class="testimonialVideo-video"><?php the_content(); ?></div>

    <div class="testimonialVideo-title">
        <strong><?php echo get_post_meta( get_the_ID(), 'video_clientName', true ) ?></strong><br/>
        <span class="small"><?php echo get_post_meta( get_the_ID(), 'video_clientCompany', true ) ?><br/><br/>
                        "<em><?php echo get_post_meta( get_the_ID(), 'video_shortQuote', true ) ?></em>"</span>
    </div>

</div>
<?php endwhile; else: ?>

<p class="error-not-found">Sorry, no testimonials found.</p>

<?php  endif; wp_reset_postdata();?>

Related posts

2 comments

  1. It seems like you need to actually prevent two specific VIDEOS from displaying on the same screen (not preventing videos from the same CLIENT twice), but if I’m wrong you can still adapt this. The idea is to push each VIDEOS identifier (name, id, whatever) to an array as you output it, checking each item against the array to see if it is already displayed on the page. If it is, skip it, if not – display it an add it to the list to prevent displaying again.

    This is what I did to avoid dupes for a randomly displayed advertisement plugin, and had a global variable containing image ids which I checked against each time an ad item was chosen to be randomly displayed.

    Other options include using meta_query (see WP_Query docs in codex) and a custom SQL query, both of which seem overly complex in my opinion. I’m not sure WP_Query can return unique results in a set of metadata or not.

    Your code adapted (I haven’t tested this code):

    <?php $test_meta_list = array(); // array to hold item names that have been displayed ?>
    <?php if ( $loop ) : while ( $loop->have_posts() ) : $loop->the_post();
    
    // Get the video meta
    $test_meta = get_post_meta( get_the_ID(), 'video_clientCompany', true )
    
    // If it has already been output, skip it
    if ( in_array($test_meta, $test_meta_list) ) 
      continue();
    // If not, add it to the list and output it
    else {
      array_push($test_meta_list, $test_meta)
    ?>
    
    <div  class="testimonialVideo top">
     <div class="testimonialVideo-video"><?php the_content(); ?></div>
       <div class="testimonialVideo-title">
         <strong><?php echo get_post_meta( get_the_ID(), 'video_clientName', true ) ?></strong><br/>
         <span class="small"><?php echo get_post_meta( get_the_ID(), 'video_clientCompany', true ) ?><br/><br/>
         "<em><?php echo get_post_meta( get_the_ID(), 'video_shortQuote', true ) ?></em>"
         </span>
       </div>
     </div>
    </div>
    <?php } endwhile; else: ?>  
    
  2. Piggybacking off of @Nick answer. What this will do it query ALL video posts in that category, checks if client1 == client2 and if it does, show the post and increment how many clients we have showing. The loop should stop after 2 posts are shown and drop out.

    Ideally you would want to run an SQL query to do this because of overhead but I don’t have enough SQL experience, so you don’t want me to write the query for you xD

    <?php
    $loop = new WP_Query(array(
            'post_type' => 'video',
            'posts_per_page' => -1,
            'orderby' => 'rand',
            'tax_query' => array(
                array(
                    'taxonomy' => 'video_category',
                    'field' => 'slug',
                    'terms' => 'assess-core-certification',
                    'operator' => 'NOT IN')
            )
        )
    );
    ?>
    
    
    
    <?php
    $prevClient = '';
    $clients = 0;
    if ($loop) :
        while ($loop->have_posts() && $client < 2) :
            $loop->the_post();
            $clientUpper = get_post_meta(get_the_ID(), 'video_clientName', true);
            $clientLower = strtolower($client);
            if ($prevClient != $clientLower) :
                $clients++;
                $prevClient = $clientLower;
                ?>
    
                <div class="testimonialVideo top">
    
                    <div class="testimonialVideo-video"><?php the_content(); ?></div>
    
                    <div class="testimonialVideo-title">
                        <strong><?php echo clientUpper; ?></strong><br/>
                        <span class="small"><?php echo get_post_meta(get_the_ID(), 'video_clientCompany', true) ?><br/><br/>
                    "<em><?php echo get_post_meta(get_the_ID(), 'video_shortQuote', true) ?></em>"</span>
                    </div>
    
                </div>
    
            <?php endif; endwhile; else: ?>
    
        <p class="error-not-found">Sorry, no testimonials found.</p>
    
    <?php endif; wp_reset_postdata();?>
    

Comments are closed.