So, first off, I would use get_posts
instead of writing your own query.
The strategy: fetch all the posts at once, then filter them using a callback or foreach
loops. What follows is a PHP 5.3+ example (anonymous functions, etc).
Let's wrap all this up in a function that will take a post type, the terms you want, and the taxonomy to which they belong.
<?php
function wpse63444_get_posts($post_type, $terms, $tax)
{
}
So then we can get the posts.
<?php
function wpse63444_get_posts($post_type, $terms, $tax)
{
$posts = get_posts(array(
'post_type' => $post_type,
'meta_key' => 'number', // the meta key
'order_by' => 'meta_value_num',
'order' => 'ASC', // might have to tweak the order a bit
'numberposts' => -1, // get ALL THE POSTS
'tax_query' => array(
array(
'taxonomy' => $tax,
'field' => 'slug',
'terms' => $terms,
'include_children' => false,
),
),
));
if(!$posts)
return array(); // bail if we didn't get any posts
}
Now that we have all the posts, and we know the terms, we can filter them into array of term => posts pairs.
<?php
function wpse63444_get_posts($post_type, $terms, $tax)
{
// snip snip
$res = array();
foreach($terms as $t)
{
// PHP < 5.3 will need something different here
$res[$t] = array_filter($posts, function($p) use ($t, $tax) {
if(has_term($t, $tax, $p))
return $p; // the post has this term, use it
});
}
return $res;
}
The entire function:
<?php
function wpse63444_get_posts($post_type, $terms, $tax)
{
$posts = get_posts(array(
'post_type' => $post_type,
'meta_key' => 'number', // the meta key
'order_by' => 'meta_value_num',
'order' => 'ASC', // might have to tweak the order a bit
'numberposts' => -1, // get ALL THE POSTS
'tax_query' => array(
array(
'taxonomy' => $tax,
'field' => 'slug',
'terms' => $terms,
'include_children' => false,
),
),
));
if(!$posts)
return array(); // bail if we didn't get any posts
$res = array();
foreach($terms as $t)
{
// PHP < 5.3 will need something different here
$res[$t] = array_filter($posts, function($p) use ($t, $tax) {
if(has_term($t, $tax, $p))
return $p; // the post has this term, use it
});
}
return $res;
}
Some example usage with normal posts and categories found in the theme unit test data.
<?php
$res = wpse63444_get_posts('post', array('cat-a', 'cat-b', 'cat-c'), 'category');
if($res)
{
foreach($res as $cat => $posts)
{
if(!$posts)
continue;
echo '<h1>', get_term_by('slug', $cat, 'category')->name, '</h1>';
foreach($posts as $p)
echo '<h2>', $p->post_title, ' ', get_post_meta($p->ID, 'number', true), '</h2>';
}
}
Here is that function wrapped up in a plugin