Abstract picture of some lights

I once read that the best way to learn programming is by reading the code that others have written. After all, most of the time you spend as a developer will probably be reviewing, polishing, and fixing code that you or another developer wrote in the past. This is precisely why I like free and open source software so much: it grants us access to the source code of great tools and makes it possible to learn from them.

If you are interested in the WordPress world (and I imagine you are, because you’re here), WordPress Core’s source code or Gutenberg‘s are two very good ways to become a better WordPress professional and learn about backend and frontend development.

Since Gutenberg’s first release, we’ve been sharing all we’ve learned about frontend development so far. Thus, for example, we made a series of posts where we taught you the basics of React, we saw how to reuse components, we explained how to extend Gutenberg, and we discussed JavaScript news to write better source code, to name a few articles we’ve written.

Well, today we’re going to shift gears and focus on WordPress Core again. Why? I don’t know, maybe because the announcement of the next Twenty Twenty-One theme that came out a few days ago is the perfect excuse to do so ?. So let’s talk about one of the most important elements when creating themes in WordPress: the get_template_part function.

Panda afraid of what it sees on its computer
Don’t worry! Let’s take it slowly.

WordPress Themes

First of all, let’s review how WordPress themes work, shall we? Essentially, a theme is a collection of files that defines the HTML structure and CSS styles our site will use.

If you think about the skeleton of any web page, you will see that the same pattern is always repeated:

  • We start by opening the html and head tags. That’s where we add scripts, styles, meta tags, and so on.
  • Then we close the head tag and open the body tag, which will contain the visible content of our website.
    • Usually, the body of a page includes a header with the logo of the web, a menu, etc.
    • Then comes the content itself, which can be a page, a blog article, a list of posts, the result of a search, and so on.
    • Finally, it usually ends with a footer.
  • Finally, once the whole page has been rendered, we close all tags and we’re done.

So, yup, it seems that every webpage follows more or less a similar structure: there’s a common part (i.e. header, menu, footer…) and a content-specific area (a blog post, the set of results we got after a search, a WooCommerce product, etc).

As programmers do not like repeating code and we are (in general) organized people, WordPress themes follow a very patterned file structure. In this post I wrote a few months ago, you have a good explanation of the different files in a theme, but keep in mind that there are:

  • a stylesheet: style.css,
  • a header.php file to “open” the web page (that is, output the head tag and, normally, the initial part of the body that’s common to all pages),
  • another footer.php file that “closes” the page (i.e. it adds the footer and closes the html tag), and
  • a lot of additional files for the different types of content that we want to render.

What is the get_template_part function and what is it for?

The first thing to do when you come across a new feature is the opposite of what you do when your father asks you to help him program his new Roomba cleaner: read the documentation . So let’s do that with our function by looking at the Codex:

get_template_part provides a simple mechanism for child themes to overload reusable sections of code in the theme.

Includes the named template part for a theme or if a name is specified then a specialised part will be included. If the theme contains no {slug}.php file then no template will be included.

The template is included using require, not require_once, so you may include the same template part multiple times.

For the $name parameter, if the file is called “{slug}-special.php” then specify “special”.

Note: get_template_part() fails silently

get_template_part docs at WordPress.org

See? In less than a minute we have obtained all the information we needed. Now we know that this function is used to create “reusable parts” in a theme (thus avoiding duplicating code) and it does so in such a way that a child theme can adapt them. We also have information about its parameters, its internal workings (it uses PHP’s require function), and what we can expect from it (it “fails silently”).

Cartoon of a happy guy

Unfortunately, there are a few things that are still unclear, like these {slug}.php and {slug}-special.php files it mentions. What are they? What do they contain? What do they do? Many difficult questions to answer by looking at the documentation only, so it’s time to jump to the examples.

How to create partial templates in our theme

Let’s take a look at the Twenty Twenty-One theme to find out if it uses these “partial templates” and, if it does, what they look like and what you should do to implement them in your own theme.

If you read my post about the file hierarchy of a WordPress theme, you will know that “index.php is the default template for our theme. It is used to render any content on our website, as long as said content does not have a specific template designed for it.” Since this is a default template, I think it’s a good idea to start there. This is the content of index.php in the Twenty Twenty-One theme :

if ( have_posts() ) {
  // Load posts loop.
  while ( have_posts() ) {
    get_template_part( 'template-parts/content/content' );
  // Previous/next page navigation.
} else {
  // If no content, include the "No posts found" template.
  get_template_part( 'template-parts/content/content-none' );
get_footer();Code language: JavaScript (javascript)

As you can see, we have all the parts that we had previously commented:

  • It includes the header using get_header.
  • It renders the content itself.
  • It closes the page with get_footer.

The interesting thing here, obviously, is the “content” area in index.php. Specifically, we see that we have a small control to know whether or not we are seeing any valid content (have_posts function of the WordPress Loop) and, depending on whether we have or not, we load a partial template (…/content) or another (…/content-none).

If we now take a look at the partial content.php template, we will roughly see the following:

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
  <header class="entry-header alignwide">
    the_title( … );
  <div class="entry-content">
    the_content( … );
    wp_link_pages( … );
  <footer class="entry-footer default-max-width">
    <?php twenty_twenty_one_entry_meta_footer(); ?>
</article>Code language: JavaScript (javascript)

Pretty straightforward, isn’t it? All we have is a tiny template designed to render generic WordPress content such as, for example, a blog post. Note that the resulting HTML skeleton is nothing more than an article tag with a title, its content, and a footer, all using WordPress template tags to pull the actual content.

Why the WordPress API is awesome

Even if you didn’t know all these functions exist (get_header, get_footer, or today’s star: get_template_part), I’m pretty sure that you would have organized your code following a similar approach. After all, it seems quite logical to create a template for the header, another for the footer, another for the content… and then have a special file or something that glues it all together, right?

If you did follow such an approach, I bet your index.php file would have looked something like this:

require_once 'header.php';
if ( have_posts() ) {
  // Load posts loop.
  while ( have_posts() ) {
    require 'template-parts/content.php';
  // Previous/next page navigation.
} else {
  // If no content, include the "No posts found" template.
  require 'template-parts/content-none.php';
require_once 'footer.php';Code language: PHP (php)

which is very similar to the one we have in the Twenty Twenty-One theme. So, at this point, you may ask yourself: what do I gain by using specific WordPress functions? Isn’t it the same to directly use a PHP require, especially considering that, according to the WordPress documentation, that’s precisely what these helper functions use?

Well, the main reason is actually mentioned in the documentation itself: it makes it easy to create child theme. Thus, if you are creating a child theme and you use get_template_part, WordPress will look for the template in the child and, if it is not, it will use the parent’s.

But that’s not all! WordPress functions are usually full of filters and actions that allow you to adapt the final result. For example, if we look at the internal function get_template_part in the wp-includes/general-template.php file :

function get_template_part() {
  do_action( "get_template_part_{$slug}", … );
  do_action( 'get_template_part', … );
  if ( ! locate_template( … ) ) {
    return false;
}Code language: JavaScript (javascript)

we’ll see that we have a couple of actions that plugins and the theme itself can leverage. And if we keep pulling the thread, we’ll even be able to see how WordPress locate (locate_template) and loads the template it’ll end up using:

function locate_template( $template_names, … ) {
  $located = '';
  foreach ( $template_names as $name ) {
    if ( file_exists( STYLESHEETPATH . "/$name" ) ) {
      $located = …; // in child theme
    } else if ( file_exists( STYLESHEETPATH . "/$name" ) ) {
      $located = …; // in parent theme
    } else {
  if ( $located ) {
    load_template( $located, $require_once, $args );
  return $located;
}Code language: PHP (php)

I hope today’s post helped you understand a little better how WordPress themes work. I also hope it showed you how to learn about WordPress by reading its documentation and browsing its source code. And if you liked it, share it with your friends and leave us a comment.

Featured image by Joshua Sortino on Unsplash.

Leave a Reply

Your email address will not be published. Required fields are marked *

I have read and agree to the Nelio Software Privacy Policy

Your personal data will be located on SiteGround and will be treated by Nelio Software with the sole purpose of publishing this comment here. The legitimation is carried out through your express consent. Contact us to access, rectify, limit, or delete your data.