5

In an attempt to speed up my query, I'm using the following arguments:

$args = array(
    'post_type' => 'product',
    'fields' => 'ids',
);

$query = new WP_Query($args);

While this does return an array of IDs as expected, I keep getting multiple Trying to get property of non-object in /wp-includes/query.php notices. This happens even when I have nothing inside my while other than the_post():

if ($query->have_posts()) : while ($query->have_posts()) : $query->the_post();
endwhile;
endif;

Is the_post() causing this? Any idea why I'm getting these notices?

3
  • What's the fields entry? Never heard of that before. Does it work when you remove that?
    – geomagas
    Commented Mar 10, 2014 at 19:21
  • The fields => ids option returns an array of post ids rather than post objects, which (apparently) makes the query faster.
    – Dre
    Commented Mar 10, 2014 at 19:28
  • I see. That explains Milo's answer then (apparently)...
    – geomagas
    Commented Mar 10, 2014 at 19:30

1 Answer 1

9

the_post places the next post object from $query->posts in the global $post and calls setup_postdata, which assumes $post is a post object, as it tries to access member vars of that object, which is where the errors come from.

In this case $posts is just an array of IDs instead of post objects. If you want to iterate over the results, you can do a foreach on $posts:

$args = array(
    'post_type' => 'product',
    'fields' => 'ids',
);
$query = new WP_Query($args);

if ($query->have_posts()):
    foreach( $query->posts as $id ):
        echo 'ID: ' . $id;
    endforeach;
endif;
5
  • Spot on. The documentation for the_post() that I found didn't cover what it actually did in great detail, so I didn't realise it was attempting to access other vars.
    – Dre
    Commented Mar 10, 2014 at 19:37
  • While using 'fields' => 'ids' may be faster on the query, it still has to go and fetch each post individually one at a time, which ends up adding a 2+ queries per post instead of just 1 (to get meta when you need it). Commented Jan 10, 2015 at 2:20
  • I did however submit a ticket to Trac which could alleviate the object errors, but I wouldn't recommend it unless you have a huge object cache with each post already stored in it, but even then it's really not optimal. My ticket involves allowing setup_postdata ($wp_query->setup_postdata) to accept a Post ID, which would be handy if you only had IDs to work with. Still, getting IDs from a WP_Query 'fields' => 'ids' should be avoided at all costs if you intend to use WP template tags and/or get post data for all posts returned by WP_Query. core.trac.wordpress.org/ticket/30970 Commented Jan 10, 2015 at 2:26
  • If you did intentionally set posts_per_page to 1, I could see the ticket I've submitted could actually help you, because 'fields' => 'ids' would be quite quick, and the overhead is small if you have object caching enabled as the post may likely already be cached so get_post may actually be faster versus getting the full objects from the DB without 'fields' => 'ids' Commented Jan 10, 2015 at 2:28
  • @ScottKingsleyClark indeed, if you intend to use WP template tags and/or get post data for all posts returned by WP_Query then you're doing it wrong by using the fields argument. I assumed that OP just needed IDs and not full post objects. I thought that was reflected in the example code I provided, but perhaps I should have been more explicit.
    – Milo
    Commented Jan 10, 2015 at 2:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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