get_posts()
is just a wrapper for WP_Query
, however it does have two main differences:
get_posts()
just returns an array of posts, so doesn’t provide methods for a Loop.get_posts()
sets theignore_sticky_posts
andno_found_rows
arguments totrue
.no_found_rows
is required for pagination, and disabling it improves performance.
#1 means means that you need to use a slightly different method for allowing the use of template tags like the_title()
. It also means that hooks like loop_start
and loop_end
will not fire.
#2 means that get_posts()
will be faster, and you don’t need to worry about sticky posts, which you almost certain don’t want included as part of a secondary loop.
However, you can achieve the performance of get_posts()
with WP_Query
simply by setting no_found_rows
to true, and you can ignore sticky posts by setting ignore_sticky_posts
to true
.
So these are essentially exactly the same:
// WP_Query
$query_dog = new WP_Query( [
'post_type' => 'animals',
'posts_per_page' => 3,
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'tax_query' => [
[
'taxonomy' => 'species',
'field' => 'slug',
'terms' => 'chien',
],
],
] );
while ( $query_dog->have_posts() ) : $query_dog->the_post();
get_template_part( 'template-parts/publication-animaux' );
endwhile();
wp_reset_postdata();
// get_posts
$posts_dog = get_posts( [
'post_type' => 'animals',
'posts_per_page' => 3,
'tax_query' => [
[
'taxonomy' => 'species',
'field' => 'slug',
'terms' => 'chien',
],
],
] );
global $post;
foreach ( $posts_dog as $post ) : setup_postdata( $post ); // *Must* be $post.
get_template_part( 'template-parts/publication-animaux' );
endforeach;
wp_reset_postdata();
Those two loops will have the exact same result, and nearly identical performance, theoretically. In the style I’ve written them they even have the exact same number of lines. So which one to use basically comes down entirely to which one you prefer.
The biggest difference is probably that the WP_Query
method triggers the loop_start
and loop_end
hooks, which some plugins might use, you you might want to use (loop_start
triggers on the first use of the_post()
, and loop_end
triggers on the last use of have_posts()
. WordPress doesn’t do anything with them on its own.
I myself prefer WP_Query
, simply because I find the direct use of the global $post
variable and setup_postdata()
to be a bit ‘hack-y’. I find get_posts()
is more appropriate when you need to query posts for something other than outputting them in a loop. WP_Query
on the other hand mimics the behaviour of the main loop, and