0

My home page include five loop.

currently i use wp_query but is it optimized ? best choice with get_posts ? my code looks like that

    // First loop
    $args_dogs = array(
    'post_type' => array('animals'),
    'posts_per_page' => '3',
    'tax_query' => array(
                     array(
                          'taxonomy' => 'species',
                          'field' => 'slug',
                          'terms' => 'chien',
                        ),
                  ),
    'orderby' => 'date',
);
$query_dog = new WP_Query( $args_dogs );
if ( $query_dog->have_posts() ) : ?>
    <?php while ( $query_dog->have_posts() ) : $query_dog->the_post(); ?>
      <?php get_template_part( 'template-parts/publication-animaux' ); ?>
    <?php endwhile; ?>
<?php endif; ?>
<?php wp_reset_postdata(); ?>



// second loop
        $args_cat = array(
        'post_type' => array('animaux'),
        'posts_per_page' => '3',
        'tax_query' => array(
                         array(
                              'taxonomy' => 'species',
                              'field' => 'slug',
                              'terms' => 'chat',
                            ),
                      ),
        'orderby' => 'date',
    );
    $query_cat = new WP_Query( $args_cat );
    if ( $query_cat->have_posts() ) : ?>
        <?php while ( $query_cat->have_posts() ) : $query_cat->the_post(); ?>
          <?php get_template_part( 'template-parts/publication-animaux' ); ?>
        <?php endwhile; ?>
    <?php endif; ?>
    <?php wp_reset_postdata(); ?>

    // the third loop use args for display the last sticky post
      $args_sticky = array(
      'posts_per_page' => 1,
      'post__in'  => get_option( 'sticky_posts' ),
      'ignore_sticky_posts' => 1
    );
    $query_sticky = new WP_Query( $args_sticky );

  // the four loop use args for display last posts and ignore sticky post

   $args_home = array(
    'posts_per_page' => 4,
    'post__not_in' => get_option('sticky_posts')
   );
   $query_home = new WP_Query( $args_home );

  // the five loop use args for display elements of cpt slider 
  $slider_args = array(
   'post_type' => array('slider'),
   'posts_per_page' => -1,
   'order' => 'DESC',//
  );
  $slider = new WP_Query($slider_args);

get_posts support my parameters..so, for optimize the performance, is it better to use get_posts ? and why concretely ? I have trouble grasping the real difference

2

1 Answer 1

2

get_posts() is just a wrapper for WP_Query, however it does have two main differences:

  1. get_posts() just returns an array of posts, so doesn't provide methods for a Loop.
  2. get_posts() sets the ignore_sticky_posts and no_found_rows arguments to true. 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

2
  • If the answer helped you then please mark it as accepted so that other users can see that your question has an answer. Feb 18, 2019 at 13:31
  • Thanks for this thorough write-up, Jacob. I've bookmarked it for future reference.
    – tmdesigned
    Feb 18, 2019 at 15:17

Your Answer

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

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