Query multiple custom post types using ratios (or similar)

I’m a bit stumped with this one. I’m using wordpress and I’d like to query multiple custom post types using some kind of ratio and display them on a page.

Let’s say I have the following post types:

Read More

tweet, project, video & post

At the moment my current query result is flooded with tweets and all the other post types are being pushed down the page.

Is there a way to formulate a query so that (say) 25% of the result is taken up by tweets and the remaining 75% taken up by the other post types? Essentially I’d like to reduce the number of tweets that are appearing in my query result.

I hope that makes sense.

Many thanks

Related posts

Leave a Reply

1 comment

  1. I would probably handle this manually with 2 separate custom queries (using WP_Query). I’m going to assume you want paging enabled (since it’s your only blogroll and eventually this will get very large). In general, the strategy is going to be:

    1) Build two different queries (1 for your projects, videos, and posts… And 1 for your tweets).

    2) Setup the ratio you’d like to mix using the posts_per_page attribute of your query arguments.

    3) Loop each query, but don’t output their titles or content just yet, but rather, store each in its own array.

    4) Create a new array to contain your “shuffled” blogroll.

    5) Loop through this new array to output the content.

    $posts_array = array(); // this will temporarily hold your projects/videos/posts
    $tweets_array = array(); // this will temporarily hold your tweets
    
    // WP_Query arguments for projects, videos, and posts
    $post_args = array (
        'post_type'              => array('project', 'video', 'post'),
        'post_status'            => 'publish',
        'pagination'             => true,
        'posts_per_page'         => '10',
    );
    
    // The Query
    $query_posts = new WP_Query( $post_args );
    
    // The Loop will be used to grab the posts and store them in $posts_array
    if ( $query_posts->have_posts() ) {
        while ( $query_posts->have_posts() ) {
            $query_posts->the_post();
    
            // here you can use any number of functions inside the loop to get content or metadata about this post
            $posts_array[] = array(
                'title' => get_the_title(),
                'permalink' => get_permalink(),
                'excerpt' => get_the_excerpt(),
                'content' => get_the_content(),
                'thumbnail' => get_the_post_thumbnail()
            );
        }
    } else {
        // no posts found, maybe handle this differently if you wish
    }
    
    // Restore original Post Data
    wp_reset_postdata();
    
    // WP_Query arguments just for tweets
    $tweet_args = array (
        'post_type'              => 'tweet'
        'post_status'            => 'publish',
        'pagination'             => true,
        'posts_per_page'         => '2',
    );
    
    // The Query
    $query_tweets = new WP_Query( $tweet_args );
    
    // The Loop will be used for your tweets
    if ( $query_tweets->have_posts() ) {
        while ( $query_tweets->have_posts() ) {
            $query_tweets->the_post();
    
            $tweets_array[] = array(
                'title' => get_the_title(),
                'permalink' => get_permalink(),
                'excerpt' => get_the_excerpt(),
                'content' => get_the_content(),
                'thumbnail' => get_the_post_thumbnail()
            );
        }
    } else {
        // no posts found, maybe handle this differently if you wish
    }
    
    // Restore original Post Data
    wp_reset_postdata();
    
    $final_array = array(); //this is the array that'll hold the shuffled post types
    
    // this loop is currently built to assume the "posts_per_page" ratio from above
    // edit these to your liking if you want to increase the number of tweets per 10 other posts
    for ($i = 0; $i < 10; $i++) {
        $final_array[] = $posts_array[$i];
    
        // after the 5th normal post, inject a tweet (we only have 2 tweets, so inject the first one)
        if ($i == 4) {
            $final_array[] = $tweets_array[0];
        }
    }
    
    // now that all 10 posts are done, throw in the last tweet next
    $final_array[] = $tweets_array[1];
    
    // now output your content in your template
    foreach ($final_array as $current_post) {
        // this will be your markup for each post so replace this with the HTML for your own template
        echo '<div class="title"><a href="' . $current_post['permalink'] . '">' . $current_post['title'] . '</a></div>';
        echo '<div class="excerpt">' . $current_post['excerpt'] . '</div>';
    
        // etc etc with any of your remaining array elements
    }
    

    I didn’t test this code, so treat it sort of like pseudocode. But the general idea is hopefully clear.

    Have fun!