0

I've been trying to change my WP_Query to get_posts methods. But I am not really sure how to check if get_posts is null or have a value.

How can i transform this WP_Query checker to appropriate get_posts checker?

This is my WP_Query checker:

$custom_query = new WP_Query($args);
if ( $custom_query->have_posts() ) {
    ...
}
1

From previous questions, I know you would want optimize your queries. There is no need to change WP_Query into get_posts for perfomance. As I stated in a another post, yes, get_posts() is faster than WP_Query because get_posts() legally breaks pagination, but what get_posts() do can be done with WP_Query.

To really understand what get_posts() does, lets look at the source code. In essence, get_posts() does the following: (lets forget about the useless parameters in get_posts())

$args = [
    'no_found_rows'       => true,
    'ignore_sticky_posts' => 1
    // Any other user passed arguments
];
$r = new WP_Query( $args );
return $r->posts;

WHAT DOES IT ALL MEAN

  • get_posts() just returns the $posts property from the query object. $posts holds an array of posts

  • 'no_found_rows' => true is what legally breaks pagination, and is one of the reasons why you should not use get_posts for paginated queries. This is also why get_posts() is faster than a normal WP_Query as by default no_found_rows is set to false.

Because get_posts() only returns an array of posts, and not the query object, you must use a normal foreach loop to loop through the posts. Another thing to note, because the query object is not returned, the template tags like the_content() is not available because the $post global is not set to the current post. In a normal loop, the_post() sets up postdata which makes template tags available. For get_posts(), we need to do this manually by using setup_postdata( $post ) in our foreach loop

To properly loop through get_posts(), we need to do something like this

$posts_array = get_posts( $args );
if ( $posts_array ) { // Make sure we have posts before we attempt to loop through them
    foreach ( $posts_array as $post ) {
        setup_postdata( $post );

        // Now we can use template tags
        the_title();
        the_content();
    }
    wp_reset_postdata(); // VERY VERY IMPORTANT
}

I would not go through all of this to change existing WP_Query instances in order to optimize them. Simply add 'no_found_rows' => true to your WP_Query arguments, and viola, you are doing exatly what get_posts() is doing

5
  • Wow you are really amazing me with your answers, @pieter. So basically, it's okay to not convert my wp_query by using no_found_rows to true, right? i've been transforming my query from query_posts to wp_query to get_posts. – karlo jay bueno Feb 19 '16 at 9:40
  • Correct, no_found_rows is all that is needed. You do not need to convert WP_Query to get_posts. Note again, make sure you do not need pagination in the query – Pieter Goosen Feb 19 '16 at 9:44
  • Yes. I am not needing pagination in all my queries. Thank you so much, @pieter. – karlo jay bueno Feb 19 '16 at 9:45
  • My pleasure. You should download and install the query monitor plugin on your local test install. This will tell you how many queries you are doing per page and how long it takes to run that queries ;-) – Pieter Goosen Feb 19 '16 at 9:48
  • thank you. You've been a great help, ever since i started asking question here. :) – karlo jay bueno Feb 19 '16 at 9:50
2

Using a simple empty function.

$wpse_posts = get_posts( $args );

if ( ! empty( $wpse_posts ) ) {
    //Do the loop

} else {
   //No post found
}
6
  • Thank you, @sumit, :). I gratefully appreciate your answer. – karlo jay bueno Feb 19 '16 at 9:27
  • Do not use $posts as a local variable, it is a reserved global variable. You are breaking that variable which causes other big issues – Pieter Goosen Feb 19 '16 at 9:31
  • @Sumit The $post AND $posts globals are set here, note the plural s in $posts – Pieter Goosen Feb 19 '16 at 9:47
  • @PieterGoosen I do not expect this downvote from you. What do you see when you print $posts in a template ? It is NULL, you first need to globalize the variable with global $variable; – Sumit Feb 19 '16 at 9:51
  • 1
    @PieterGoosen I've accepted the truth. I definitely not arguing with you. I am just saying downvote is not good when question does not say that I am in main loop. function myposts() { return $posts; } print_r(myposts()); and print_r($posts) have difference. You assumed the code directly in template. I assumed it in functions.php within in a function – Sumit Feb 19 '16 at 10:05

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.