Using meta_query, how can i filter by a custom field and order by another one?

With the following code (in functions.php) my posts (of CPT event) are ordered by _end_date instead of _start_date. What’s the proper solution to this as of WP 3.1.3? Of course I’d like to avoid using deprecated meta_key.

add_filter( 'pre_get_posts', 'my_get_posts' );
function my_get_posts( $query ) {
if ( is_home() ) {
  $query->set( 'post_type', 'event' );
  $query->set( 'meta_key', '_start_date' );
  $query->set( 'orderby', 'meta_value_num' );
  $query->set( 'order', 'ASC' );
  $query->set( 'meta_query', array(
                                   array(
                                         'key' => '_end_date',
                                         'value' => time(),
                                         'compare' => '>=',
                                         'type' => 'numeric'
                                        )
                                   )
                              );
  }
  return $query;
}

Related posts

Leave a Reply

1 comment

  1. This seems to be a bug in WordPress. WordPress actually modifies the meta_query if you specify orderby and meta_key as query vars. Normally this modification adds the new meta_key as the first array in meta_query array and hence the orderby is applied to the first meta key specified in meta_query.

    But when you modify orderby, meta_key and meta_value query_vars in pre_get_posts filter, due to the (it seems to me) bug in WordPress, it add the new array in existing meta query but the new array is not inserted as first array, it gets appended to the existing meta_query. And orderby always gets applied to the first meta_key in meta_query.

    So as a workaround until the bug gets fixed you can specify the meta_key again in the meta_query as the first array, as in the following example:

    add_filter( 'pre_get_posts', 'my_get_posts' );
    function my_get_posts( $query ) {
    if ( is_home() ) {
      $query->set( 'post_type', 'event' );
      $query->set( 'meta_key', '_start_date' );
      $query->set( 'orderby', 'meta_value_num' );
      $query->set( 'order', 'ASC' );
      $query->set( 'meta_query', array(
            array(
                  'key' => '_start_date'
            ),
            array(
                  'key' => '_end_date',
                  'value' => time(),
                  'compare' => '>=',
                  'type' => 'numeric'
            )
      ));
      }
      return $query;
    }