In the earlier parts of this series, you've learned how theme frameworks work and have considered your approach to the framework you're developing.
Now it's time to dive into some code!
In this tutorial you'll take a basic theme and edit the template files so they're ready for hooks and functions to be added to them for your framework. The purpose of this tutorial is to tidy up the theme so that code isn't duplicated, which means you'll be creating include files for the loop.
This means you won't have to create duplicate loops in your child themes when you create new template files, and if you need to edit the loop you only have to do it once.
Note: the starting files are based on the theme I created for my series on creating a WordPress theme from HTML, with a few changes. You can download them from the GitHub repository accompanying this series.
What You'll Need
To follow this tutorial, you'll need:
- a development installation of WordPress
- your own starting theme or the starting theme files in the GitHub repository for this series
- a code editor
Creating Include Files for the Loop
For my framework I'm going to create three loops:
- one for archives (including the main blog page)
- one for single posts
- one for pages
This is because I want each of these to display slightly differently than the others.
Even though there'll be three loops, it will still be more efficient than including a loop in every single template file in your framework.
The Main Loop
The main loop will be for archives and the main blog page. In your theme folder, create a file called loop.php
.
Copy the following into it from archive.php
:
<?php /* Queue the first post, that way we know if this is a date archive so we can display the correct title. * We reset this later so we can run the loop properly with a call to rewind_posts(). */ if ( have_posts() ) the_post(); ?> <h2 class="page-title"> <?php if ( is_day() ) { ?> Archive for <?php echo get_the_date(); } elseif ( is_month() ) { ?> Archive for <?php echo get_the_date('F Y'); } elseif ( is_year() ) { ?> Archive for <?php echo get_the_date('Y'); } else { echo get_queried_object()->name; } ?> </h2> <?php rewind_posts(); ?> <?php // start the loop ?> <?php while ( have_posts() ) : the_post(); ?> <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <h2 class="entry-title"> <a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'compass' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"> <?php the_title(); ?> </a> </h2> <section class="left image quarter"> <?php if ( has_post_thumbnail() ) { ?> <a href="<?php the_permalink(); ?>"> <?php the_post_thumbnail( 'medium', array( 'class' => 'left', 'alt' => trim(strip_tags( $wp_postmeta->_wp_attachment_image_alt )) ) ); ?> </a> <?php } ?> </section><!-- .image --> <section class="entry-meta"> <p>Posted on <?php the_date(); ?> by <?php the_author(); ?></p> </section><!-- .entry-meta --> <section class="entry-content"> <?php the_content(); ?> </section><!-- .entry-content --> <section class="entry-meta"> <?php if ( count( get_the_category() ) ) : ?> <span class="cat-links"> Categories: <?php echo get_the_category_list( ', ' ); ?> </span> <?php endif; ?> </section><!-- .entry-meta --> </article><!-- #01--> <?php endwhile; ?> <?php // ends the loop ?>
You don't need to display a heading on the main blog page, so add a conditional tag around the first loop, to check that we're not on that page:
if ( ! is_front_page() ) { }
The first loop will now read as follows:
if ( ! is_front_page() ) { if ( have_posts() ) the_post(); ?> <h2 class="page-title"> <?php if ( is_day() ) { ?> Archive for <?php echo get_the_date(); } elseif ( is_month() ) { ?> Archive for <?php echo get_the_date('F Y'); } elseif ( is_year() ) { ?> Archive for <?php echo get_the_date('Y'); } else { echo get_queried_object()->name; } ?> </h2> <?php rewind_posts(); } ?>
Now you need to include this loop in the relevant template files. In archive.php
and index.php
, replace the existing loop with the get_template_part()
tag, which includes your loop file in the right place:
<?php get_template_part( 'loop' ); ?>
You now have a working loop for archives.
Page Loop
Next you'll create a loop file for pages. Create a file called loop-page.php
.
Copy the loop to it from the existing page.php
:
<?php // Run the page loop to output the page content. if ( have_posts() ) while ( have_posts() ) : the_post(); ?> <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <?php if ( ! is_front_page() ) { ?> <h2 class="entry-title"><?php the_title(); ?></h2> <?php } ?> <section class="entry-content"> <?php the_content(); ?> </section><!-- .entry-content --> </article><!-- #post-## --> <?php endwhile; ?>
Now in all your theme's page templates (page.php
and page-full-width.php
), replace the loop with:
<?php get_template_part( 'loop' , 'page' ); ?>
Single Post Loop
Finally, you'll create a loop file for single posts, which will work for normal posts and for any custom post types you create in future. This is similar to the main loop except that it doesn't include a link to the post, and there's no initial loop to check what kind of archive we're on.
Create a file called loop-single.php
and another called single.php
.
Copy the contents of the index.php
file into single.php
, and edit the comments at the beginning of the file and the call for the loop, so it reads:
<?php get_template_part( 'loop', 'single' ); ?>
Now in single-loop.php
, copy the code in loop.php
, not including the first loop looking for archives. Edit the opening heading tag inside the loop to remove the link, so that the code reads:
<?php while ( have_posts() ) : the_post(); ?> <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <h2 class="entry-title"> <?php the_title(); ?> </h2> <section class="left image quarter"> <?php if ( has_post_thumbnail() ) { ?> <a href="<?php the_permalink(); ?>"> <?php the_post_thumbnail( 'medium', array( 'class' => 'left', 'alt' => trim(strip_tags( $wp_postmeta->_wp_attachment_image_alt )) ) ); ?> </a> <?php } ?> </section><!-- .image --> <section class="entry-meta"> <p>Posted on <?php the_date(); ?> by <?php the_author(); ?></p> </section><!-- .entry-meta --> <section class="entry-content"> <?php the_content(); ?> </section><!-- .entry-content --> <section class="entry-meta"> <?php if ( count( get_the_category() ) ) : ?> <span class="cat-links"> Categories: <?php echo get_the_category_list( ', ' ); ?> </span> <?php endif; ?> </section><!-- .entry-meta --> </article><!-- #01--> <?php endwhile; ?>
Save these two files. You now have all of your loop files ready to go.
Summary
Tidying up a theme and reducing duplicate code before using it as at the basis of a theme framework will save you hours of work in the long run.
As you create child themes to work with this parent theme, you'll find yourself creating bespoke loops to simply create content in exactly the right way for a given project. By only having three discrete loops to work with, you'll avoid the necessity of creating duplicate template files in your child theme and you'll just have to create duplicate loop files.
Comments