Coding the WordPress Loop

Have you ever downloaded a WordPress theme with sloppy code?

There’s probably a good chance you have. Either more than 90% of themes have sloppy code or by some astronomically improbable chance, I only ever happen to download themes with sloppy code. I’m hoping to open the eyes of at least a small percentage of theme authors and help usher in a new era of neater code.

I’m going to break down the basics of the WordPress Loop in this post and help you write cleaner themes. I’ll explain each line of code along the way and point out references to the outside information.

I know. I know. A post about The Loop doesn’t sound too exciting, but maybe this is just what we need — a journey back to the basics. Take a look at the example file to see what The Loop should look like. The important thing here is not to focus on the code but to notice how the code is formatted. See the plentiful whitespace? I’d like to see more of that in themes.

More seasoned theme authors might have slightly different methods for displaying content than in this guide. This should serve as a reference, or a starting point, for using correct WordPress template tags and proper code formatting.

What is The Loop?

The Loop is what makes WordPress go. It’s how all of the WordPress magic happens. It’s the most important thing. Everything else is secondary.

To be more specific, it cycles through posts, allowing us to display them in any manner we want.

The first step: Opening The Loop

Before we display our posts, we have to open The Loop. Most theme authors know how to get this right, which at least shows potential.

<?php if(have_posts()) : while(have_posts()) : the_post(); ?>

Notice that before the loop starts, we are actually checking if there are any posts. The if(have_posts()) checks if there are any posts available. If there are posts, we should loop through them.

The while(have_posts()) begins the loop. It will begin a continuous cycle, looping through each post available for display.

the_post() calls up information about the post that we’ll be using and sets the global $post variable.

That’s quite a lot for one line of code, right? It’s pretty important stuff.

Resources:

Displaying the post

This next step is all about a simple line of code that is commonly referred to as the post div. We want to wrap all of our post content into one div to kind of hold it all together.

<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

the_ID() gives us the ID of the post. Each post has a unique ID.

post_class() is a WordPress 2.7+ function that provides post-specific classes for use in your stylesheet. This is a neat feature because you can display posts with specific tags, categories, and so on differently than other posts.

Resources:

The post title

There are a few different ways you could code the post title, but I’ll show you my favorite method.

<?php the_title('<h2 class="entry-title"><a href="' . get_permalink() . '" title="' . the_title_attribute('echo=0') . '" rel="bookmark">', '</a></h2>'); ?>

the_title() is the WordPress template tag for showing the post title. Pretty simple, right? It takes up to three optional parameters: before (before the title), after (after the title), and display (whether to display or return it for use in a function).

The get_permalink() template tag gives us the post URL. It’s the permanent link to the post.

the_title_attribute() is a template tag I don’t see often enough. Anytime you put a post title in the title attribute of a hyperlink, don’t use the_title(). Use the_title_attribute(). This takes care of those pesky posts with things such as quotation marks, leaving us with valid XHTML.

Alternately, you can use single_post_title() for displaying a post title in the single.php and page.php templates.

Resources:

The byline

Byline is a term often used in journalism that denotes the writer of a story. Blogs are essentially like newspapers or magazines in this way. You could also go as far as adding a dateline, but I like to add my post author, post time, and edit link all within the byline paragraph before the post text.

<p class="byline">
	<span class="author vcard"><?php the_author_posts_link(); ?></span> <span class="sep">|</span>
	<abbr class="published" title="<?php the_time(__('l, F jS, Y, g:i a', 'example')); ?>"><?php the_time(__('F j, Y', 'example')); ?></abbr>
	<?php edit_post_link(__('Edit', 'example'), ' <span class="sep">|</span> <span class="edit">', '</span> '); ?>
</p>

The first template tag we see in this block of code is the_author_posts_link(). This displays a link to the author’s archive page. Alternately, you could use the_author if you only want to display the author’s display name.

the_time() displays when the post was published. There are several formats you can use for this to get just the right look. You may be wondering why there are two instances of the_time() in my code. The first is set in an abbr element’s title attribute. I’ve done this so that when a reader hovers over the time display, they’ll see an expanded version with more details.

The edit_post_link() displays a link to edit the post to only logged-in users that have the capability to edit posts. Otherwise, the link is not shown. Clicking on it will take you to the edit post screen in the WordPress dashboard.

Resources:

Displaying the post content

There are two different methods for displaying post content. You can display the entire post or an excerpt. The first method I’ll show you is of displaying the entire post. You should use always use this in single.php and page.php. Most themes will use this method in home.php or index.php as well.

<div class="entry-content">
	<?php the_content(__('Continue reading', 'example')); ?>
	<?php wp_link_pages('before=<p class="pages">' . __('Pages:','example') . '&after=</p>'); ?>
</div>

Note that I’m wrapping the post content in its own div here. This gives us better separation and more styling options.

the_content() displays the entire post. It doesn’t get much simpler than that. Continue reading is the text shown in the link when the post author cuts off the post with the tag.

wp_link_pages() is a piece of code that’s not added to enough themes. This is a vital piece of code! When an author uses the quicktag to break his or her posts into more than one page, we need to display the links to each page.

If you only want to display the excerpt of the post, follow along. Displaying the excerpt is useful for any archive-based template files, such as category.php and date.php, and search.php.

<div class="entry-summary">
	<?php the_excerpt(); ?>
</div>

This will display either the first 55 words of a post or the text entered into the Excerpt textarea when on the Write Post panel in the WordPress dashboard.

Resources:

Showing the post metadata

After showing the post content, I generally display the post metadata, which is additional information about the post. I like to put the category, tags, and comments link in this section. You can combine this with the byline and/or mix and match the two however you want.

<p class="entry-meta">
	<span class="categories"><?php _e('Posted in', 'example'); ?> <?php the_category(', '); ?></span>
	<?php the_tags('<span class="tags"> <span class="sep">|</span> ' . __('Tagged', 'example') . ' ', ', ', '</span>'); ?>
	<span class="sep">|</span> <?php comments_popup_link(__('Leave a response', 'example'), __('1 Response', 'example'), __('% Responses', 'example'), 'comments-link', __('Comments closed', 'example')); ?>
</p>

the_category() shows your post categories. I’m using a comma as the separator in the code above. You can use anything you like there to separate multiple categories.

the_tags() displays all of your post tags. Notice how it looks a bit different than the display of the categories though — everything is tucked neatly away inside of the_tags(). Doing it this way assures that the tags or any additional text you add will only display if the user tags the post. This keeps users that don’t use tags from getting frustrated with seeing Tagged followed by nothing.

The last part of the post metadata that we’ll show is a link to the comments of the post. The template tag for this is comments_popup_link(). It’s important to use this because it serves two purposes: links to a pop-up window for users that are using pop-up comments or links to the post comments for users that aren’t using pop-up comments. Note that this won’t work on single.php and page.php because you’ll already be on the page with the comments list.

Resources:

Closing The Loop

The tough part is over. Now we must close this thing off to make it all work correctly. We must also display a message in case no posts were found.

	</div>

	<?php endwhile; ?>

<?php else : ?>

	<p class="no-posts"><?php _e('Sorry, no posts matched your criteria', 'example'); ?></p>

<?php endif; ?></code></pre>

## Localization

The more observant of you may have noticed the several instances of text with the word <code>example</code> in it, like these lines:

<pre><code>__('Pages:','example')
_e('Sorry, no posts matched your criteria', 'example')

This process is referred to as localization, which makes your WordPress theme ready for translation. I’ll cover this in a later post in more detail. Making your theme ready to use in any language should be something to consider.

Resources:

Start writing cleaner loops

Now that I’ve shown you the proper template tags and have pointed out loads of resources, I expect you theme authors to start making cleaner themes.

Fancy gizmos and gadgets don’t impress me much. Some cool JavaScript feature isn’t so cool if your code isn’t understandable.

Think about your theme users. I know most of us theme developers don’t like for users to muddle in our code, but the honest truth is that end users tinker with the code. Of course, there are countless ways to do things without diving into the templates, but they’ll continue doing it anyway. The best thing we can do for them is make the code as readable as possible.

Clean code also helps others learn from what you’ve done. Why not help a new theme designer looking at your theme code by making things a little neater?