WordPress Theming – Partial Templates with get_template_part()

Introduction

It used to be that WordPress theme templates were monolithic beasts, with a fair bit of looping and conditional logic to display content in a certain way. I know, I’ve done it too. In past years, this has been helped somewhat with the availability of content-type-specific template files, such as page.php, attachment.php, and so on. This helped to reduce the monolithic aspect of, say, index.php and single.php. However, the result was repeated code across multiple files (almost even a multitude). Repeated and redundant code should make any coder cringe. Well, there is a further step to take with the use of a little function called get_template_part().

Introducing get_template_part()

get_template_part() was introduced in WordPress 3.0, and is a more general form of existing functions used to pull in template code from another file (such as header, footer, and sidebar). Indeed, it is now possible to have common code in one file, and use the function to include template code pertinent to a particular content type. The specific files could be termed partials, or fragments.

The function signature looks like this:

get_template_part({general}, {specific});

The first parameter is required, while the second is optional. If both parameters are used, the function attempts to include a file with the following name:

{general}-{specific}.php

If the {specific} parameter is not given, or if it is given and the resulting combination filename does not exist, the function will try to include the {general}.php file. If the {general}.php file does not exist, no file is included. In any situation where the expected partial file does not exist, the general fallback is tried, and if that does not exist, the function ends without errors.

To reiterate, the function behaviour works as follows, stopping with the first action that succeeds:

  1. Include {general}-{specific}.php
  2. Include {general}.php
  3. Exit without error

Another advantage is that the inclusion is always done relative to the theme’s directory, so there is no need to worry about file paths.

This function seems simple, yet when used appropriately can be used to break down theme templates into reusable modules, reducing redundant code and the need for large logic blocks.

get_template_part() is a generalization, is intended to be used for consuming template partials, and is not suitable where existing specialty functions already exist, such as get_header(), get_footer(), and get_sidebar().

An Example Implementation

A common task in theming is looping through content to present a list of e.g. posts or pages. These are often done in different contexts, including author, tag, category, and date archives as well as the index template. Regardless of context, the main loop is usually done similar to the following:

<?php
if (have_posts()):
    while (have_posts()):
        the_post();
?>
<!-- template markup goes here -->
<?php
    endwhile;
else: // no posts found
?>
<p>No posts found matching your criteria.</p>
<?php
endif; // done checking for posts
?>

It’s not a long block of code, but it would have to be repeated in at least the contexts mentioned above. If the output markup was to be kept the same in these contexts, and a change was introduced in one context, the same change would need to be introduced in the other locations as well. That’s just cringe-inducing.

Suppose that this common loop code could be extracted into a fragment, loop.php. In each of the contexts listed above, the common looping code could be replaced with:

get_template_part('loop');

The code block above, based in loop.php, would be dynamically loaded into the current context, executed, and output the resulting markup. This is all well and good if the generated markup is intended to be the same in each context. But if not, then this is an opportunity for get_template_part() to shine.

If a certain context, say the author archive, requires different markup output compared to the other contexts, a specialized loop fragment can be introduced as loop-author.php. Perhaps the other contexts have a common way of showing posts, with thumbnails and metadata, but the author archive is preferred to just have a list of text links to the author’s posts. That’s where loop-author.php would come in; the overall loop would remain the same, but the markup can be changed. The author archive template file can then use the specialized fragment with the following code:

get_template_part('loop', 'author');

The resulting filename would be loop-author.php, and the matching file will be loaded and executed. The contents of loop-author.php could look like the following:

<?php
if (have_posts()):
?>
<ul>
<?php
    while (have_posts()):
        the_post();
?>
    <li><a href="<?php the_permalink() ?>"><?php the_title() ?></a></li>
<?php
    endwhile;
?>
</ul>
<?php
else: // no posts found
?>
<p>No posts found matching your criteria.</p>
<?php
endif; // done checking for posts
?>

Yes, it’s simplistic, but the point is that the posts listing can be generated differently for the author archive versus the other archive types. The output will resemble the following image:

Author archive posts listing, using an author template fileOutput of simple get_template_part() implementation.

Following from this, it would be possible to have different loop outputs for each of these contexts, retaining the generic loop.php for cases where no special customization is needed. Whether that would be needed is another matter, but the point is that the use of this technique allows coders to compartmentalize theme components with minimal extra work.

Conclusion

I didn’t learn about get_template_part() until several months ago, even though it has been in WordPress for some time. Once I understood it, however, I quickly realized the ways it can be used to componentize themes and template files, noticeably reducing repeated code yet allowing for customizing output in different contexts. All without requiring large blocks of logic code to determine what to display. This function can be a workhorse, and should be a part of any theme developer’s toolbox.

Additional Reading