Using rewind_posts for displaying multiple categories

Your main problem is that the cat param accept an integer (a term_id) as value, not a string of comma separed ids…

You have to use category__in argument in your case.

Read here for more info.

Another problem is the use of showposts argument: setting it to 2 you’ll get 2 posts in total, not 2 posts per category.

What I suggest you:

if functions.php create a function like this:

function get_posts_for_cat_ordered( $cats = array(), $posts_per_cat = 2 ) { 
  if ( empty($cats) ) return false;
  $args = array('posts_per_page' => 99, 'category__in' => $cats, 'orderby' => 'rand');
  $q = new WP_Query( $args );
  $posts_ordered = array();
  $done = 0;
  while ( $q->have_posts() ) : $q->the_post();
    global $post;
    $cats = get_the_category();
    $cat = array_shift( $cats );
    if ( ! isset($posts_ordered[$cat->slug]) )
      $posts_ordered[$cat->slug] = array('term' => $cat);
    if ( ! isset($posts_ordered[$cat->slug]['posts']) )
      $posts_ordered[$cat->slug]['posts'] = array();
    if ( count($posts_ordered[$cat->slug]['posts']) == $posts_per_cat ) {
       $done++;
       if ( $done == count($cats) ) return $posts_ordered;
       continue;
    }
    $posts_ordered[$cat->slug]['posts'][] = $post;
  endwhile;
  wp_reset_postdata();
  return $posts_ordered;
}

This function take an array of categories and a number of post you want retrieve for every category and return a multidimensional array with posts ordered per category.

After that use the function just created like so:

$cats = array(12, 13, 14);
$posts_per_category = 2;
$posts_ordered = get_posts_for_cat_ordered( $cats, $posts_per_category );

if ( ! empty($posts_ordered) ) { foreach ( $posts_ordered as $loop_data) {

  // Example category heading
  echo '<h2><a href="' . get_term_link($loop_data['term'], 'category') . '">' . $loop_data['term']->name . '</a></h2>';
  global $post;
  foreach ( $loop_data['posts'] as $post) {
    setup_postdata($post);
?>

  <!-- Example post content -->
  <?php the_title(); ?><br />
  <?php the_content(); ?><br />

<?php
  }
  wp_reset_postdata();

} }

Note that I’ve also

  • changed the showposts argument (deprecated) with posts_per_page
  • added wp_reset_postdata after the custom queries loop.

Possible issues:

If a post has more than one category this code may not worked as expected. But a little change in the get_posts_for_cat_ordered function can solve this issue. However, if you don’t need this feature, leave code as is, because is more performant.

Another issues can happen if in the blog there is no enough posts for each wanted category inside the last 99 posts.
This is for the 'posts_per_page' => 99 argument in the query used in the get_posts_for_cat_ordered function. I’ve used that number because is a reasonable high number, and if the blog has thousands of posts the fucntion will not affect performance.

Both these issues will not stop the function to work, but the showed posts can be less than expected if the described situations will occur.