1

I'm altering the main WP_Query to get all posts with a certain meta value using pre_get_posts, like this:

add_action( 'pre_get_posts', 'public_loop' );

public function public_loop( $query ) {
    if ( ! is_admin() && $query->is_main_query() ) { 
        $query->set( 'meta_key', 'deadline' );  
    }
}

Then I'm loading older posts via AJAX, so I need to create a new query which I want to have the same paremeters as the main query I've altered. Passing the parameters as arguments works, as expected:

function load_new_posts() {

    $q = new WP_Query( array( 'meta_key' => 'deadline' ) );

    if ( $q->have_posts() ) :
        while ( $q->have_posts() ) : $q->the_post();
            get_template_part( 'views/post/content', get_post_format() );
        endwhile;           
    endif;

}

But passing them using the set method doesn't:

function load_new_posts() {

    $q = new WP_Query();

    $q->set( 'meta_key', 'deadline' );

    if ( $q->have_posts() ) :
        while ( $q->have_posts() ) : $q->the_post();
            get_template_part( 'views/post/content', get_post_format() );
        endwhile;           
    endif;

}

In the second case, the AJAX call says "This request has no response data available". However, if I var_dump( $q ) the query looks correct.

I would rather use the set way so I can create a reusable function (since I use it both in pre_get_postsand in the AJAX call).

  • pre_get_posts applies to any WP_Query call, which means to your AJAX one too. If you set a variable $q = new WP_Query( array( 'custom_query_var_xyz' => true ) );, then you can use the get method inside pre_get_posts, e.g. $query->get( 'custom_query_var_xyz' ) to get the variable and thereby distinguish your query, and then set the the query parameter conditionally. – Nicolai Nov 4 '17 at 17:00
3

In the last example (the one that's not working for you), you're instantiating an instance of the WP_Query class without passing in an array of query vars. That's fine, but internally this means the query never actually takes place. You're calling $q->set( ... ), but that's only setting a query variable, it doesn't run the query and retrieve results.

To actually run the query and populate results, do one of two things:

  • Pass query vars to the class constructor.

    $q = new WP_Query( array( 'meta_key' => 'deadline' ) );
    
  • Or, run the query after instantiating.

    $q = new WP_Query();
    $q->query( array( 'meta_key' => 'deadline' ) );
    

What will not work, is this:

$q = new WP_Query();
$q->set( 'meta_key', 'deadline' );
$q->query( array() );

It doesn't work, because the query() method sets and overrides any existing query variables. Therefore, you can't use set() in this particular case. Keep in mind, the reason set() works well from the filter in your first example, is because the filter event occurs within the WP_Query class internally. But when you perform a query using the WP_Query class yourself, you must explicitly pass in a set of query vars that establish the query that needs to be run.

  • Beautifully explained, thank you. Just one doubt: if I run the query after instantiating it doing $q->query( array( 'meta_key' => 'deadline' ) );, and then I need to alter that query at a later moment, or want to reuse it somewhere else but adding a few arguments, how can I do that? – grazianodev Nov 4 '17 at 18:04
  • @grazianodev Quite welcome. ~ Save query vars in a variable; e.g., $query = array( ... );. Modify and reuse $q by calling $q->query( $query ); again. Having said that, I advise against this, as it mutates an existing query that was already performed. You lose the prior set of results entirely. From the standpoint of good design, it would generally be better to instantiate a new instance of WP_Query for each query that you're going to run. If you don't need the previous query, simply do not reference it again, and PHP's internal garbage collector will free it from memory as necessary. – jaswrks Nov 4 '17 at 18:14

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.