views:

1320

answers:

3

There seem to be three main ways to output content from Wordpress using its built-in functions, with WP_Query being the recommended one:

What are the differences between them? (I understand that WP_Query is the class, and the other two are methods).

What is the cleanest way to have multiple loops on the same page, without any of them interfering with each other?

I'm looking for examples of how you program your WP loops; e.g. output 2 separate post lists by category, with attachments, meta data etc.

This is the best reference I found so far:

+3  A: 

From the WP docs for get_posts:

get_posts() can also take the parameters that query_posts() can since both functions now use the same database query code internally.

The only difference between the two functions is that get_posts returns an array with post records, while query_posts stores the records in the query object for retrieval by the template functions (has_posts, the_post, etc).

They both use the WP_Query object to execute the query.

Creating a second loop is covered in the Wordpress docs. There are some links there for other examples of multiple loops. You'll notice that everyone does it differently, but they all seem happy with their results.

Todd Rowan
+2  A: 

I've used both WP_Query and get_posts. On one of my sidebar templates, I use the following loop to display posts from a particular category by using custom fields with a key of 'category_to_load' which contains the category slug or category name. The real difference comes in the implementation of either method.

The get_posts method looks like so in some of my templates:

<?php    
    global $post;
    $blog_posts = get_posts($q_string);
    foreach($blog_posts as $post) : 
    setup_postdata($post);
?>
           <div class="blog_post">
             <div class="title">
               <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
               <span class="date"><?php the_time('F j, Y'); ?> by <?php the_author(); ?></span>
             </div>
             <?php the_excerpt(); ?>
           </div>
     <?php endforeach; ?>

Where the WP_Query implementation looks like this:

$blog_posts = new WP_Query('showposts=15');

while ($blog_posts->have_posts()) : $blog_posts->the_post(); ?>

      <div <?php post_class() ?> id="post-<?php the_ID(); ?>" class="blog_post">
       <div class="title">
         <h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
         <span class="date"><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></span>
       </div>
       <div class="entry">
        <?php the_content(); ?>
       </div>
       <p class="postmetadata"><?php the_tags('Tags: ', ', ', '<br />'); ?> Posted in <?php the_category(', ') ?> | <?php edit_post_link('Edit', '', ' | '); ?>  <?php comments_popup_link('No Comments &#187;', '1 Comment &#187;', '% Comments &#187;'); ?></p>
      </div>

     <?php endwhile; ?>

The main difference being that you don't have to reset the global $post variable and you also don't have to set up the post data by calling setup_postdata($post) on each post object when you use WP_query. You can also use the lovely have_posts() function on the WP_Query function, which is not available using get_posts().

You shouldn't use the query_posts() function unless you really mean to because it modifies the main loop for the page. See the docs. So if you're building a special page to display your blog on, then calling query_posts may mess up the page's loop, so you should use WP_Query.

That's just my two cents. My ultimate suggestion, your first choice should be WP_Query.

-Chris

Christopher Hazlett
How would you access the post children (attachments, revisions etc.). Would this be a separate query?
meleyal
you can use the get_children() function: http://codex.wordpress.org/Function_Reference/get_children. OR You can use wp_list_pages - wp_list_pages('title_li= ?> : http://codex.wordpress.org/wp_list_pages if you want a list. -C
Christopher Hazlett
+1  A: 

WP uses an object called $wp_query for the main loop. We usually don't see this object because it's hidden behind have_posts() and the_post() that are only wrappers for $wp_query->have_posts() and $wp_query->the_post()

If you want to modify the main loop you should use query_posts() before the loop.

If you want another loop you can reutilize the $wp_query object using query_posts() before that new loop. This can be done many times if needed.

If for some reason you need to keep the $wp_query object around THEN you should use WP_Query. And of course, because have_posts() and the_post() are wrappers for $wp_query object you can't use them with WP_Query. You should rather use $your_query_obj->have_posts() i.e.

$sidebar= WP_Query('category_name= sidebar');

while( $sidebar->have_posts() ): $sidebar->the_post();
  the_title();
  the_content();
endwhile;

A good case where WP_Query could be better than query_posts() is a left sidebar. As the code loop for the sidebar will probably be put on top of the main loop, a query_posts() call will have changed the $wp_query object and also changed the main loop. In this case to use query_posts() at the sidebar code you will also need to use query_posts() before the main loop to query the proper content for that loop.

So using WP_Query for this case will keep $wp_query and therefore the main loop untouched.

But again, for a common case scenario query_posts() is a beautiful way to query your content:

query_posts('category_name=blog');

while( have_posts() ): the_post();
  the_title();
  the_content();
endwhile;
Julio Protzek