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!
Leave a Reply