The Ultimate WordPress Theme Tutorial (6)

The WordPress Theme Index Template

Posted on  by Ian Stewart

Index.php is the most crucial WordPress Theme Template. Not only because WordPress needs to use it if you’re missing any of it’s brother and sister templates (like, category.phpor tag.php) but because the work we do here, getting this template right, will help us breeze through the rest of our templates (with the exception of the dreaded comments template; that’s just plain difficult no matter how you look at it).

The Loop

Even though it’s stuck right in the middle of your template, in a metaphorical senseindex.php begins and ends with The Loop. Without it you don’t have anything. Here’s what it looks like.

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

Simple really. And not even deceptively simple. While you’ve got posts in your database your theme will loop through them and for each one, do something. Getting the “do something” just right is the tricky part. But even that can be simple.
Try out this loop to get started and we’ll work on building it up. Put the following code inside your #content div in index.php.

<?php while ( have_posts() ) : the_post() ?>
<?php the_content(); ?>
<?php endwhile; ?>

What do you get if you do that? All the post content in a big smushed up pile. But it could be different.

<ul>
<?php while ( have_posts() ) : the_post() ?>
<li>
    <?php the_excerpt(); ?>
</li>
<?php endwhile; ?>
</ul>

Do you see what we just did there? Now you’ve got an unordered list of post excerpts. (Plus, now you can see what the_content() and the_excerpt() do)
Basically, you make a loop (starts with while ends with endwhile) and put some stuff in it—stuff being WordPress Template Tags that pull information out of the posts we’re looping though, just like bloginfo() pulled information out of our WordPress settings in the last lesson.
Alright, let’s make a really awesome loop. Let’s start with our basic, smushed up one. But we’ll make sure it’s ready for the More Tag and the Next Page Tag. We’ll also put it in it’s own div and let machines know it’s the content of a blog post with the microformat class “entry-content”.

					<div>
<?php the_content( __( 'Continue reading <span>&raquo;</span>', 'your-theme' )  ); ?>
<?php wp_link_pages('before=<div>' . __( 'Pages:', 'your-theme' ) . '&after=</div>') ?>
					</div><!-- .entry-content -->

How about the post title? That’s pretty simple too. We’ll use the Template Tag the_title()to get the title of the post and wrap it in an <a> tag that links to the_permalink() (that’s the permanent link to any particular post). We’ll also add in a title attribute and another microformat (bookmark) that tells machines (like Google) that this is the permalink to a blog post. Try putting the following just above the .entry-content div.

					<h2><a href="<?php the_permalink(); ?>" title="<?php printf( __('Permalink to %s', 'your-theme'), the_title_attribute('echo=0') ); ?>" rel="bookmark"><?php the_title(); ?></a></h2>

Now for all the extra bits that attend to any blog post: who wrote it, the time it was published, categories, tags, comments links. I like to break all this up into two sections: the meta stuff (author and entry date) which I put before the post content, and the utility stuff (categories, tags and comments link) that I put after the content. And both sections We’ll also put the post in it’s own containing div with the title.
Let’s take a look at the whole loop together. I’ve inserted some PHP comments in here to help guide you along.

<?php /* The Loop — with comments! */ ?>
<?php while ( have_posts() ) : the_post() ?>
<?php /* Create a div with a unique ID thanks to the_ID() and semantic classes with post_class() */ ?>
				<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<?php /* an h2 title */ ?>
					<h2><a href="<?php the_permalink(); ?>" title="<?php printf( __('Permalink to %s', 'your-theme'), the_title_attribute('echo=0') ); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
<?php /* Microformatted, translatable post meta */ ?>
					<div>
						<span><?php _e('By ', 'your-theme'); ?></span>
						<span><a href="<?php echo get_author_link( false, $authordata->ID, $authordata->user_nicename ); ?>" title="<?php printf( __( 'View all posts by %s', 'your-theme' ), $authordata->display_name ); ?>"><?php the_author(); ?></a></span>
						<span> | </span>
						<span><?php _e('Published ', 'your-theme'); ?></span>
						<span><abbr title="<?php the_time('Y-m-dTH:i:sO') ?>"><?php the_time( get_option( 'date_format' ) ); ?></abbr></span>
						<?php edit_post_link( __( 'Edit', 'your-theme' ), "<span class="meta-sep">|</span>ntttttt<span class="edit-link">", "</span>nttttt" ) ?>
					</div><!-- .entry-meta -->
<?php /* The entry content */ ?>
					<div>
<?php the_content( __( 'Continue reading <span>&raquo;</span>', 'your-theme' )  ); ?>
<?php wp_link_pages('before=<div>' . __( 'Pages:', 'your-theme' ) . '&after=</div>') ?>
					</div><!-- .entry-content -->
<?php /* Microformatted category and tag links along with a comments link */ ?>
					<div>
						<span><span><?php _e( 'Posted in ', 'your-theme' ); ?></span><?php echo get_the_category_list(', '); ?></span>
						<span> | </span>
						<?php the_tags( '<span><span>' . __('Tagged ', 'your-theme' ) . '</span>', ", ", "</span>ntttttt<span class="meta-sep">|</span>n" ) ?>
						<span><?php comments_popup_link( __( 'Leave a comment', 'your-theme' ), __( '1 Comment', 'your-theme' ), __( '% Comments', 'your-theme' ) ) ?></span>
						<?php edit_post_link( __( 'Edit', 'your-theme' ), "<span class="meta-sep">|</span>ntttttt<span class="edit-link">", "</span>ntttttn" ) ?>
					</div><!-- #entry-utility -->
				</div><!-- #post-<?php the_ID(); ?> -->
<?php /* Close up the post div and then end the loop with endwhile */ ?>
<?php endwhile; ?>

Navigation

Now we need a way to navigate back through our posts. We’ll do this with 2 WordPress Template Tags: next_posts_link() and previous_posts_link(). These 2 functions … they don’t do what you think they do. I think the WordPress codex says it best.

next posts link
This creates a link to the previous posts. Yes, it says “next posts,” but it’s named that just to confuse you.
previous posts link
This creates a link to the next posts. Yes, it says “previous posts,” but it’s named that just to confuse you.

Just like everything in index.php, post navigation needs to be given some careful thought when we’re building it for the first time because we’re going to wind up using it on almost every page in our blog.
I like to have post navigation above and below the content. Depending on how you use this code in any particular situation, you may not use it though. No matter, we can always hide it like so.

.single #nav-above {
    display:none;
}

That CSS will hide post navigation above the content on single posts.
We’ll also want to hide any navigation code IF there’s nothing to navigate too. That is, if, say, on a search, there are no older pages of posts, we don’t want to output any navigation code at all to the browser. We’ll do that by wrapping our code in the following statement:

<?php global $wp_query; $total_pages = $wp_query->max_num_pages; if ( $total_pages > 1 ) { ?>
<?php } ?>

What we’re doing is checking to see what the maximum number of pages is in any loop we’re going to be looking at and if the number of pages is greater than 1, we’ll output our navigation.
Alright, here’s the code we’ll need for your navigation, top and bottom, just before, and just after the loop.

<?php /* Top post navigation */ ?>
<?php global $wp_query; $total_pages = $wp_query->max_num_pages; if ( $total_pages > 1 ) { ?>
				<div id="nav-above">
					<div><?php next_posts_link(__( '<span>&laquo;</span> Older posts', 'your-theme' )) ?></div>
					<div><?php previous_posts_link(__( 'Newer posts <span>&raquo;</span>', 'your-theme' )) ?></div>
				</div><!-- #nav-above -->
<?php } ?>
<?php /* Bottom post navigation */ ?>
<?php global $wp_query; $total_pages = $wp_query->max_num_pages; if ( $total_pages > 1 ) { ?>
				<div id="nav-below">
					<div><?php next_posts_link(__( '<span>&laquo;</span> Older posts', 'your-theme' )) ?></div>
					<div><?php previous_posts_link(__( 'Newer posts <span>&raquo;</span>', 'your-theme' )) ?></div>
				</div><!-- #nav-below -->
<?php } ?>

One last thing and we’re done index.php. You’ll be itching to see what we can do with it, but for now we’re just going to put in the function call just before get_footer().

<?php get_sidebar(); ?>

How To Create a WordPress Theme

This post is part of a WordPress Themes Tutorial that will show you how to create a powerful WordPress Theme from scratch. Read it from the beginning and code yourself up something awesome.