Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have 3 posts types, articles, news and tips. On the home page I want to query 20 posts in this order:

article, article, news, news, tip, ...// same order again until 20

If I use a custom query like so:

$query = new WP_Query(array(
  'post_type' => array('articles', 'news', 'tips'),
  'posts_per_page' => 20,
));

I get 20 items but how to order them? Would it be possible to make 3 different queries and then merge the results?

share|improve this question

2 Answers 2

You could try a modified version of this answer :

add_filter('posts_orderby', 'custom_posts_orderby');

$query = new WP_Query(array(
  'post_type' => array('articles', 'news', 'tips'),
  'posts_per_page' => 20,
));

remove_filter('posts_orderby', 'custom_posts_orderby');

where

function custom_posts_orderby($orderby) {
    global $wpdb;
    return $wpdb->posts .".post_type ASC,".$wpdb->posts .".post_date DESC";
}

So the posts are first ordered by post_type (asc) and then by post_date (desc).

share|improve this answer

You definitely could use three different queries and then merge them.

// Query 7 items per Custom Post Type.
// A, A, N, N, T, T will result in 8 x A, 6 x N and 6 x T.
$atricles = new WP_Query( 'post_type=article&posts_per_page=8' ); // A
$news     = new WP_Query( 'post_type=news&posts_per_page=6' ); // N
$tips     = new WP_Query( 'post_type=tips&posts_per_page=6' ); // T

// Assign new array keys to the queried posts
$stp = 0; $key = 0; $arr = array();
foreach ( $articles->posts as $post_obj ) { $key++; $arr[$stp + $key] = $post_obj; if ( $key === 2 ) { $stp += 6; $key = 0; } }
$articles->posts = $arr;

$stp = 2; $key = 0; $arr = array();
foreach ( $news->posts as $post_obj ) { $key++; $arr[$stp + $key] = $post_obj; if ( $key === 2 ) { $stp += 6; $key = 0; } }
$news->posts = $arr;

$stp = 4; $key = 0; $arr = array();
foreach ( $tips->posts as $post_obj ) { $key++; $arr[$stp + $key] = $post_obj; if ( $key === 2 ) { $stp += 6; $key = 0; } }
$tips->posts = $arr;

// Modify one object to contain all Posts
// Use the + array union operator to preserve the array keys
$articles->posts = $articles->posts + $news->posts + $tips->posts;

// Sort the array by keys.
ksort( $articles->posts );

// Don't forget to "reset" the post_count variable in the modified object.
// This way you will have 20 posts instead of the queried 8 (in this case).
$articles->post_count += $news->post_count;
$articles->post_count += $tips->post_count;

// Use the modified result object for the loop
while ( $articles->has_posts() ):
  $articles->the_post();

  // Do your stuff with it :-)
endwhile;

This may look like a very odd way to do this, but this way you can use the loop and preserve the option to use pagination. Although a direct query to the database can be quicker I guess.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.