James Muspratt
Feb 27
Cheat Sheet: Wordpress Loops
The default Loop
Most of the built-in Wordpress templates are set up so that they automatically retrieve and prepare a particular group of posts for output: For example, tag.php
will retrieve all posts tagged as “nashville” when the user visits http://example.com/tag/nashville
. To access and output these posts, you put your post functions (the_title()
, the_content()
, etc.) inside a series of nested if/while/the_post statements that look like this:
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
<?php the_content(); ?>
<?php endwhile; else: ?>
<p>Sorry, no posts found.</p>
<?php endif; ?>
When the page loads, Wordpress retrieves all the posts tagged as “nashville”, then outputs the post content according to your formatting inside the loop statement above. This exact code can be used on all of the common templates (index.php
, page.php
, category.php
, tag.php
, and single.php
).
The key thing to remember is that when you use the default Loop, you can’t see the database query. Wordpress has already made the query based on information in the URL. This makes some intuitive sense: since the if/while/the_post() conditions are accessing a database query that has already occurred, it must have come from the template type itself, not from any particular PHP in your template.
Using get_posts()
In anything but the simplest site, you’ll occasionally want to display post content or links outside of the default Loops. To do so, you need to (1) store your query preferences in an array, (2) run a database query function called get_posts()
to retreive the posts, and (3) access the results with an additional loop.
Let’s suppose we have a regular template set up, but we want to add an unordered list of links that contains the 5 most recent posts in the “News” category. Since this will go in our home page sidebar, we open up index.php
and add our code in the appropriate <div>
or <section>
there.
To review, we’ll use get_posts()
outside of the default loop using these three steps:
- Store our database query preferences in an array called
$args
- Pass
$args
into get_posts() and store the returned result in$myposts
- Run a
foreach
loop on $myposts to access the content of each post in turn.
<h2>Recent News</h2>
<ul id="recent-news">
<?php
// 1. store our loop preferences in an array
$args = array(
'numberposts' => 5, // notice this has to be "numberposts", not "posts_per_page"
'category' => '4', // FEATURES category
'orderby' => 'post_date',
'order' => 'DESC', // the other option is ASC
'post_type' => 'post',
'post_status' => 'publish'
);
// 2. Run get_posts() on the $args array and store the result in $myposts
$myposts = get_posts( $args );
// 3. Run a foreach loop on $myposts to access our content, combined with the annoying-but-necessary setup_postdata function.
foreach( $myposts as $post ) : setup_postdata($post); ?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endforeach; ?>
</ul>
Using wp_query()
This is the nuclear option, useful for those occasions where you need to create multiple loops and control every aspect of them. It requires some object-oriented syntax (notice the resreed keyword “new” used before wp_query), which we haven’t covered, but you can often get far by copying and pasting examples from the web.
Here’s an example:
<?php
// Create two queries and store them in different variables
$featured_query_ = new wp_query('category_name=featured', 'posts_per_page=5','order=DESC');
$news_query = new wp_query('category_name=news', 'posts_per_page=5','order=DESC');
?>
<h2>Recent Featured Posts</h2>
<ul>
<?php while ( $featured_query_->have_posts() ) : $featured_query_->the_post();
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; ?>
</ul>
<h2>Recent News</h2>
<ul>
<?php while ( $news_query->have_posts() ) : $news_query->the_post();
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; ?>
</ul>