Combining queries with different arguments per post type

I am building a section on a site where I am merging two different post types into one loop, and then displaying them randomly. The problem is, I’m having a hard time finding a way to limit the amount of posts per type.

Here’s what I’ve tried:

Read More
  • One query with multiple post types can be achieved with an array:

    $args = array( 'post_type' => array( 'photos', 'quotes' ), ...
    

    … but cannot limited to a certain number of posts per type.

  • Merging two query argument arrays before running WP_Query on it:

    $photos = array( 'post_type' => 'photos', 'posts_per_page' => 15, 'orderby' => 'rand' );
    $quotes = array( 'post_type' => 'quotes', 'posts_per_page' => 5, 'orderby' => 'rand' );
    
    $args = $photos + $quotes;
    // Also tried array_merge( $photos, $quotes );
    

    No luck on this. What happens is the latter variable $quotes overwrites $photos and only shows the quotes.

  • Merging two WP_Query objects together through typecasting:

    $photos_query = new WP_Query( $photos );
    $quotes_query = new WP_Query( $quotes );
    $result = (object)array_merge( (array)$photos_query, (array)$quotes_query );
    

… and so on.

I could probably use an SQL query straight to the database, but I need to be able to combine these two separate post types for one loop, arranged randomly, AND limited to a certain amount of posts per type.

Thanks for your help!

Related posts

Leave a Reply

2 comments

  1. One way is to customize the SQL query executed using posts_clauses or other such filters. To find them search for posts_clauses in “wp-includes/query.php” & see the series of filters just before this line. These together are capable of customizing any part of the query

    Another thing you can do is manually merge the queried posts in the objects

    $photos_query = new WP_Query( $photos );
    $quotes_query = new WP_Query( $quotes );
    $result = new WP_Query();
    
    // start putting the contents in the new object
    $result->posts = array_merge( $photos_query->posts, $quotes_query->posts );
    
    // here you might wanna apply some sort of sorting on $result->posts
    
    // we also need to set post count correctly so as to enable the looping
    $result->post_count = count( $result->posts );
    
  2. @mridual aggarwal your answer is very very good but unfortuntly it is not really combining the 2 wp_query it is only shows the posts from both in arrange i mean 5 posts from the first & 5 from the second but not sorted all in one so i have this solution & it exactly achieved the goal for my self at least

    <?php
    $term = get_term_by( 'slug', get_query_var( 'tag' ), "post_tag" );
    $tagslug = $term->slug;
    $post_types = get_post_types('','names');
    ?>
    <?php
    //first query
    $blogposts = get_posts(array(
        'tag' => $tagslug, //first taxonomy
        'post_type' => $post_types,
        'post_status' => 'publish',
        ));
    //second query
    $authorposts = get_posts(array(
        'bookauthor' => $tagslug, //second taxonomy
        'post_type' => $post_types,
        'post_status' => 'publish',
        ));
    $mergedposts = array_merge( $blogposts, $authorposts ); //combine queries
    
    $postids = array();
    foreach( $mergedposts as $item ) {
    $postids[]=$item->ID; //create a new query only of the post ids
    }
    $uniqueposts = array_unique($postids); //remove duplicate post ids
    
    $posts = get_posts(array(
            //new query of only the unique post ids on the merged queries from above
        'post__in' => $uniqueposts,  
        'post_type' => $post_types,
        'post_status' => 'publish',
        ));
    foreach( $posts as $post ) :
    setup_postdata($post);
    ?>
    // posts layout
    <?php endforeach; ?>
    <?php wp_reset_postdata();?>