Pass arguments to WP_Query using “set” method

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.