WP_Query To Get Custom Posts Type Posts By A Taxonomy Term With Fallback Posts

This blog will demonstrate how to make a WP_Query to get 5 posts of a custom post type by a taxonomy term and if we don’t have enough, then we fill the remaining slot using default posts as a fallback.

/**
 * Get Posts By Taxonomy.
 *
 * 1. Make a query by taxonomy and return if we have sufficient results.
 * 2. If we don't make a query to get default posts ( get extra posts so that we can remove previously
 * found posts, to avoid 'post__not_in' query )
 * 3. Merge the found post ids with previous ones and make return a fresh query by those ids in that order.
 *
 * @param int    $number    The number of posts to return.
 * @param string $taxonomy  Taxonomy.
 * @param string $term_slug Term slug
 *
 * @return WP_Query
 */
function get_posts_by_taxonomy_query( int $number = 4, string $taxonomy = 'your-taxonomy', $term_slug = 'your-term-slug' ) {

   $args = [
      'posts_per_page'         => $number,
      'post_type'              => 'your-post-type',
      'no_found_rows'          => true,
      'update_post_meta_cache' => false,
      'update_post_term_cache' => false,
      'tax_query'              => [
         [
            'taxonomy' => $taxonomy,
            'field'    => 'slug',
            'terms'    => $term_slug,
         ],
      ],
   ];

   $post_tax_query  = new WP_Query( $args );
   $post_by_tax_ids = wp_list_pluck( $post_tax_query->posts, 'ID' ); // So that we don't have to do query twice,when we have sufficient results
   $the_post_count = count( $post_by_tax_ids );

   // If we have sufficient no of results, early return.
   if ( $number == $the_post_count ) {
      return $post_tax_query;
   }

   // Otherwise get default posts and merge the two set of ids.
   $args['tax_query']        = [];
   $args['fields']           = 'ids';
   $args['posts_per_page']   = ( $number - $the_post_count ) + $the_post_count; // So that duplicates could be removed later.
   $post_default_post_query = new WP_Query( $args );
   $ids                      = array_merge( $post_by_tax_ids, $post_default_post_query->posts );

   // Get the posts and with retained order.
   $all_posts_args = [
      'post__in'       => $ids,
      'posts_per_page' => $number,
      'orderby'        => 'post__in',
   ];

   return new WP_Query( array_merge( $args, $all_posts_args ) );

}

That’s all folks!


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *