The Loop is incredibly foundational to WordPress. It's the first (and possibly the easiest) thing that most new themers want to try modifying... and you can get incredibly creative with it once you know the basics. Today, we're going to lay a foundation for everyone who's new to the loop or has ever wanted to know a little bit more about exactly how it works.
The core of WordPress' functionality lies within what's called The Loop. It's a very simple concept to grasp, and understanding this will allow you to be well on your way to theme development. You can (and should!) check out the official codex page on the loop, but today's instruction is going to be geared towards people who don't necessarily enjoy scouring the codex.
In layman's terms, the loop is a simply a block of code that displays all of the information that WordPress has about a post(s) or page(s). Like the name suggests, it loops through each post that it finds in the database sequentially (one, then another, then another), so it can handle supplying information about several posts.
Before we dive into the code, let's lay out what the loops does. There are three crucial parts of it:
- Start the loop.
- Do something with each post/page found in the loop.
- Close the loop.
That's pretty simple right? The loop will, by default, retrieve everything that it can possibly find... so there's just one more piece worth noting: the query. The query is what we'll use to filter the entire stack of posts for just what we're looking for. So, our "layman's model" when we want to pull a specific set of posts looks like this:
- Define what we're looking for.
- Start the loop.
- Do something with each post/page found in the loop.
- Close the loop.
If you've ever worked with PHP before, you might be familiar with the
while function that is commonly used to loop through a database query and dynamically display the database information without having to manually enter every single database row. For the non-PHP'ers out there, think of the
while function as a nifty little librarian that retrieves everything that you want from the database, one entry at a time.
Now let's take a look at what that "layman's model" looks like in the actual code:
<?php query_posts( 'tag=apples' ); if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> // DO SOMETHING WITH EACH POST THAT WE FOUND <?php endwhile; else: ?> // DO SOMETHING IF NOTHING WAS FOUND <?php endif; ?>
I learn best by example, so let's just dive into WordPress' default Twenty Ten theme and look at what the loop is doing there.
Section 1 WordPress' Twenty Ten Theme
WordPress has a default theme that comes with every WordPress installation and is activated by default. This year's is called Twenty Eleven, but we'll be using last year's theme, Twenty Ten, as our example because it isolates the loop in it's own file (which makes illustrating our lesson a little easier). If you navigate to wp-content/themes/twentyten you will notice a file structure like we see below:
Twenty Ten separates out the loop from the other theme files. Open up index.php and note the following code:
<?php /* Run the loop to output the posts. * If you want to overload this in a child theme then include a file * called loop-index.php and that will be used instead. */ get_template_part( 'loop', 'index' ); ?>
We'll dissect the code that it is requesting soon, but it's important to know that all this is doing is requesting the page loop-index.php. If you're familiar with PHP already, include() is similar to the WordPress function get_template_part(). It is also perfectly acceptable to pull all the code out of loop-index.php and put it in the place of the code above. It will accomplish the same thing. A loop is allowed to exist within a page, and does not have to be a separate page.
We're going to open loop.php next and examine what the core loop accomplishes.
The first part of loop.php is creating pagination, but if you scroll down to line 31 - we'll notice a key element: an if statement that is asking if their are posts. This code states "if there are no posts, display a message stating there are none".
<?php if ( ! have_posts() ) : ?> Your code or HTML that states there is no content for the query. <?php endif; ?>
Down to line 56 and you'll see another crucial element of the loop:
<?php while ( have_posts() ) : the_post(); ?>
This is the while statement I mentioned earlier. It can basically be read out loud as "However long it has posts, do this loop." Then immediately you see the_post(). This function pulls all the post information so that we can show the post information using standard WordPress tags (more on this later).
Then to close the loop at line 173, you'll simply see an endwhile. The real magic and usefulness of the loop is what happens between these lines.
Imagine having to update HTML every time you want to post a blog. This would be incredibly painful and I would imagine it would discourage you to blog. I wouldn't even bother. The loop allows you to enter a blog post into a database and pull out the content into a format you design once which it will follow always. The only thing you need is to know how to manipulate the loop to display what you want and how to show the content you want.
Section 2 Displaying The Content
For the remainder of this tutorial, all the magic we'll be creating will be after the while and before the endwhile.
It's really easy to display the information you want in the WordPress Loop. I would strongly suggest reading over the WordPress Codex's Template Tags article; that will show you all the tags you can use in the loop. I'll present to you some of the things WordPress included in the Twenty Ten theme.
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
First up is the_ID(). This is the unique ID of that post, no post or page will share an ID. If you don't have URL rewrites on, you will see this ID in the URL of the post. In this example, it's useful to add it to the div id so that in CSS you can style that single post without effecting the format of all the other posts. Next is the post_class which will add a CSS class that correlates to the post type it is. If it's a post, you have a class of post. If it's an attachment, you'll have the class of attachment. Read the codex for more information on post_class();
On the next line, you'll notice two widely used tags. First is
<?php the_permalink(); ?>
This is usually wrapped in a <a href> element because it prints out the raw permalink: http://yoursite.com/?p=123 The link the post can always be reached at - which is not pretty sometimes - is automatically echoed out when you use the_permalink() tag.
Right after that tag, you'll see:
<?php the_title(); ?>
This is, as the naming suggests, the title of the post. When making the post, whatever you put as the title will show up here.
Moving down to line 109, you'll see some conditional tags that would benefit us to pull apart.
<?php if ( is_archive() || is_search() ) : // Display excerpts for archives and search. ?>
This can just be read out loud as "If we are currently on the archive page or search page, display the content as follows". This is soon after followed by
<?php the_excerpt(); ?>
But wait - in the else of this condition you'll see:
<?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'twentyten' ) ); ?>
What's the difference? the_excerpt() is going to pull just a WordPress or user defined amount of text of the post. Which is helpful on archives or searches so that the whole post isn't returned when the user is just skimming to get the drift and see if they'd like to continue reading. the_content() is going to pull the entire formatted post up to the <!--more--> tag. Which is appropriate when displaying the article on certain pages when it's not competing for attention
get_the_category_list( ', ' ); $tags_list = get_the_tag_list( '', ', ' );
The above are a few other tags within the loop you should know. The first line will pull out every category the post is associated with, and display them with a comma delimiter. The second will do the same with the tags associated with the post.
Section 2 Manipulating the Loop
Now that we know how to display our content within the loop, let's talk about getting down and dirty with the loop to get it to return exactly what we want.
The first way to manipulate the loop, is to edit the loop directly. Before the while you want to add a qualifying query_posts() function so that it looks like this:
<?php query_posts('category_name=baseball&posts_per_page=10'); ?> <?php while (have_posts()) : the_post(); ?>
In the query_posts, you're able to define arguments that are going to give you more control as to what you're displaying. With the conditional above, I have said I only want to pull posts from the category named baseball and I only want to display 10 at a time on the page. This is really simple to use as you're only adding a line of code.
Another way to do this would be to define a variable that creates a new query for the database and essentially a new loop.
$my_query = new WP_Query('category_name=baseball&posts_per_page=10');
Our while statement then requests the classes from the $my_query object, so now it looks like:
$my_query = new WP_Query('category_name=baseball&posts_per_page=10'); while ($my_query->have_posts()) : $my_query->the_post(); //code endwhile;
This can be helpful if you want to add a second loop to your page. Use one loop to display posts in one category on the left, and another category on the right. There a ton of practical uses for this and you will more than likely find yourself needing it at some point.
WordPress covers a third example of altering a loop in their Codex which I feel is a very pertinent item to go over. It's called nesting. Nesting is basically having a loop within a loop. The WordPress Codex mentions it could be useful when using short codes. I'll go ahead and let you know - yes it's useful in short codes and custom fields. Imagine having a custom field that you can fill in with post IDs that are a part of the same series (IE: wp.tutsplus.com has a running tutorial part 1, 2, and 3), and then have the loop pull the title, excerpt and other information about the post. This is one way to accomplish that task.
The nested loop is just like the loop we created above that is defined by a variable, with one important piece of code at the end of it:
$my_query = new WP_Query('category_name=baseball&posts_per_page=10'); while ($my_query->have_posts()) : $my_query->the_post(); //code endwhile; wp_reset_postdata();
You'll notice wp_reset_postdata() in this loop. This resets the global
$post variable to the current post in the main query.... which is useful for nested loops as well as anytime you want
$post working after the fact. Thanks to Rarst for the clarification on this!
Unfortunately, there's not much documentation from WordPress about the functionality of wp_reset_postdata() at this moment. It seems the only use of the function is for resetting the loop.
Do you feel like a loop master now? This was a very extensive look into the loop. The loop itself is not difficult to understand, but it's so foundational to everything else you'll run into in WordPress. The loop is where it all starts, where all your post content is generated. I hope you learned something. Feel free to leave some comments if you need some further help!