0

I've got a fairly complicated post type archive page that I need to order by two meta fields and the post title. To do that, I'm using pre_get_posts with a meta_query that simply tests for the existence of two meta-keys. It's entirely to allow for the complex ordering required. This wasn't working until I accidentally used the wrong syntax.

Why does this code work? Update: "Fixed" snippet to show the wrong-but-functioning code. h/t @SallyCJ. Update 2: Fixed the fixed snippet so keys are correct.

<?php
add_action( 'pre_get_posts', 'wpse_pre_get_posts' );
function wpse_pre_get_posts( $query ) {
    if( ! $query->is_main_query() ) {
        return;
    }

    if( is_post_type_archive( 'my-post-type' ) ) {

    $query->set( 'meta_query', array(
            'relation'      => 'OR',
            array( // this array shouldn't be here but is required for the ordering to work
                'meta_query_1'  => array(
                    'key' => 'cis_schools_is_model',
                    'type'  => 'numeric',
                    'compare'   => 'EXISTS',
                ),
                'meta_query_2'  => array(
                    'key' => 'cis_schools_district',
                    'compare'   => 'EXISTS',
                ),
            ),
        ));

        $query->set( 'orderby', array(
            'meta_query_1'      => 'DESC',
            'meta_query_2'   => 'ASC',
            'title'             => 'ASC',
        ));

    }
}

My expectation is that the extra array wrapping the two keyed meta queries (meta_query_1 and meta_query_2) shouldn't be necessary like this:

<?php
$query->set( 'meta_query', array(
    'relation'      => 'OR',
    'meta_query_1'  => array(
        'key' => 'meta-key-1',
        'type'  => 'numeric',
        'compare'   => 'EXISTS',
    ),
    'meta_query_2'  => array(
        'key' => 'meta-key-two',
        'compare'   => 'EXISTS',
    ),
));

However, the first snippet works and the second doesn't.

  • Sorry, which first snippet? And I don't see anything wrong in your meta_query.. – Sally CJ Oct 24 '18 at 22:22
  • Sorry about that @SallyCJ. I've updated the first snippet to be accurate ("wrong" but working). – mrwweb Oct 24 '18 at 23:11
  • I tested your code, and both worked for me - the orderby was correct with and without the array() wrapping. Are you sure the second one didn't work for you? Or could it be because of the mismatched keys as in the question (snippet #1) - e.g. model_school should be meta_query_1.. ? In my tests, both snippets resulted in GROUP BY wp_posts.ID ORDER BY CAST(wp_postmeta.meta_value AS SIGNED) DESC, CAST(mt1.meta_value AS CHAR) ASC, wp_posts.post_title ASC. – Sally CJ Oct 25 '18 at 1:43
  • I'm using WordPress 4.9.8, if that helps. (And btw, ignore the GROUP BY wp_posts.ID part.) – Sally CJ Oct 25 '18 at 1:50
  • Fixed the meta_query keys in the first example. They do match, I just did a horrible job of trying to anonymize the snippet. – mrwweb Oct 25 '18 at 3:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.