2 orderby in wp_query with 2 custom fields

If you look at the Codex for WP_Query you will notice that orderby is not a valid parameter for a meta_query, nor is order, and in fact nor is meta_key.

But even if that were sorted out, I don’t think you can do what you are trying to do with WP_Query. A meta_query is a WHERE clause element, which makes it a kind of search and I don’t think that is what you want. If all of your posts have those keys set then EXISTS might get you part of the way there, but it would exclude anything without one of those keys. Something like this:

'meta_query' => array(
    array(
        'key' => 'Rating',
        'compare' => 'EXISTS'
    ),
    array(
        'key' => 'Number_persons',
        'compare' => 'EXISTS'
    )
)

But ordering is still a problem and I don’t see a way around it other than a filter on posts_orderby.

function double_meta_posts_orderby($orderby) {
  global $wpdb;
  return " {$wpdb->postmeta}.meta_value, mt1.meta_value";
}

And put all together…

$args = array(
'post_type' => 'hotel',
    'Services' => $Services,
    'Town' => $Town, 
    'meta_query' => array(
  array(
        'key' => 'Number_persons',
        'compare' => 'EXISTS'
      ),
      array(
        'key' => 'Rating',
        'compare' => 'EXISTS'
      ),    
)
);
add_filter('posts_orderby','double_meta_posts_orderby');
$query = new WP_Query( $args );
remove_filter('posts_orderby','double_meta_posts_orderby');

Again, that is only going to work if all of your posts have those meta_keys. You could use the posts_joins to join the meta table yourself or you could just remove the WHERE clause with…

function kill_where($where) {
  return '';
}
add_filter('posts_where','kill_where');

Note that you are adding the filters and then removing it immediately after the query runs. If you want to avoid the need for that take a look at this answer for another option, or make the filters self-removing…

function double_meta_posts_orderby($orderby) {
  remove_filter('posts_orderby','double_meta_posts_orderby');
  global $wpdb;
  return " {$wpdb->postmeta}.meta_value, mt1.meta_value";
}

Leave a Comment