For this second edition of the “how to better code WordPress themes” series, I want to cover properly including files and templates in WordPress themes. This is one of those areas that many themes seem to get wrong.
You might not think loading a file would be such a difficult task, but there are some things you have to be considerate of in WordPress. Things can get confusing for a newcomer to WordPress theme development because there are specific functions a developer should use in certain cases. Sometimes these functions have hooks that WordPress fires that plugins can take advantage of. And, child themes should always be considered when loading files.
This tutorial will walk you through everything you need to know about loading files in WordPress.
Getting the appropriate path
No discussion on loading files would be complete without covering the correct way of getting paths. There are two important terms you need to understand when referring to paths in WordPress themes.
- Template: This refers to the directory the theme templates are located in. When using a parent/child theme setup, it refers to the parent theme.
- Stylesheet: This refers to the directory the theme stylesheet is located in. This will always be the currently activated theme, so when using a parent/child theme setup, it refers to the child theme.
If you didn’t figure it out on your own, “template” and “stylesheet” refer to the same directory when you’re not using a child theme. It’s important to know that there’s a difference because you wouldn’t want to use a stylesheet constant or function when trying to include a file from the parent theme directory.
WordPress gives you two constants to the template and stylesheet directories that you may use:
Deprecated in WordPress.
TEMPLATEPATH: Returns the absolute template directory path.
Deprecated in WordPress.
STYLESHEETPATH: Returns the absolute stylesheet directory path.
You also have several functions available for getting the path:
get_template_directory(): Returns the absolute template directory path.
get_template_directory_uri(): Returns the template directory URI.
get_stylesheet_directory(): Returns the absolute stylesheet directory path.
get_stylesheet_directory_uri(): Returns the stylesheet directory URI.
The biggest thing to note about the above functions is that the
Using require() and include()
Most WordPress themes will never need to use functions such as
include_once(). These are standard PHP functions for loading files. However, there are some uses cases where they’re needed.
Theme developers should never use these functions to load a theme template file. WordPress has functions that should always be used for loading templates, even functions for custom templates (covered later).
Most uses of the include/require functions are going to be within a theme’s
functions.php file. For example, you might have organized your theme functions into separate files or you may be using a framework to build your theme. For now, suppose you have a separate file called
widgets.php within your theme folder that defines some custom widgets. You could load this widgets functions file as shown below.
require_once( trailingslashit( get_template_directory() ). 'widgets.php' );
Remember, the term “template” refers to the template (parent theme) directory. So, if you were loading this file from within a child theme, you’d code it a little differently.
require_once( trailingslashit( get_stylesheet_directory() ) . 'widgets.php' );
One thing I’ve seen in some themes is the use of the
get_template_part() function (described below) to load a functions file like this. Using the
widgets.php example, the code would look like:
get_template_part( 'widgets' );
This is absolutely the wrong way to load function files. Please do not do this. That’s a template-loading function, which will allow child themes to overwrite the file. That’s not what you want to happen in this scenario. You should always use an include/require function for loading files such as this.
Loading theme templates
Templates are files that WordPress themes use to display content. This is very much different than loading a functions-type file. Templates house a mixture of PHP and HTML to set the site structure and output content.
In this section, I’ll walk you through each of the template-loading functions WordPress has available. These functions cover all scenarios for loading templates. When loading a template, you should always use one of these functions.
There are several reasons the use of these functions is important.
- You never have to check if a file exists before trying to include it.
- Works with child themes, allowing the child theme to overwrite templates within the parent theme.
- No need to worry about the correct path since WordPress figures it out for you.
- Some functions execute hooks that plugins might use to perform specific functionality.
get_header() function is for getting the theme header. By default, it loads a template called
header.php as shown in the code below.
<?php get_header(); ?>
You can also load a more specific template file by specifying the
$name parameter. The code below will check if the
header-blog.php file exists. If not, it will fall back to the basic
<?php get_header( 'blog' ); ?>
Loading a footer template works the same way as loading a header template. You’ll just use a different function and file(s). The basic function call loads the
<?php get_footer(); ?>
You can also pass the
$name parameter to load a more specific footer template. The code below looks for the
footer-home.php template and falls back to
footer.php if it doesn’t exist.
<?php get_footer( 'home' ); ?>
If you read my blog, you should already know how to load a sidebar template. I covered this in the Sidebars in WordPress tutorial. I recommend reading that tutorial since it goes into some more specifics about sidebar usage.
Like the header and footer template functions, a basic sidebar template function call will load the
<?php get_sidebar(); ?>
$name variable will allow you to check for a specific template. The example below will load
sidebar-special.php and fall back to the standard
sidebar.php if it doesn’t exist.
<?php get_sidebar( 'special' ); ?>
Search form template
The search form is a bit different from the previous functions covered. When using the
get_search_form() function, WordPress will look for the
searchform.php file. If this file isn’t found, WordPress will output its own search form.
If your theme doesn’t include a
searchform.php file, the output of the WordPress-generated search form can be filtered by plugins using the
Most theme developers know that the
comments_template() function loads the
comments.php template by default. However, you can actually load a different file by specifying the first parameter.
Basic usage would load the
<?php comments_template(); ?>
Suppose you wanted to display something different for comments on pages, you could load a
comments-page.php template by using this code within your theme’s
<?php comments_template( '/comments-page.php' ); ?>
get_template_part() was the fun new function WordPress 3.0 added for theme developers, but some theme authors have went overboard with its usage. I’ve seen this used in all kinds of ways, so I want to make sure theme developers are using this properly.
The function was created so that theme developers could create reusable sections (“parts”) of code within their templates. For example, a developer could create one
loop.php file to handle The Loop rather than recoding it in several templates. As with the other template functions, this allows child themes to overwrite these template parts.
This function should not be used to just load any file in a WordPress theme. It’s for template parts.
<?php get_template_part( $slug, $name = null ); ?>
The function takes in two parameters and works in much the same was as
get_sidebar(). The big difference here is that this function is for custom templates rather than standard WordPress templates.
$slug: This is the file slug for the default version of the template. This parameter is required.
$name: A more specific version of the template to load. If it doesn't exist, fall back to the default template. This parameter is optional.
Suppose you wanted to create a
loop.php file to house the code for The Loop in your theme, which would allow you to cut back on your coding requirements (this is done in the Twenty Ten theme). The code below would allow you to load this template part into other templates.
<?php get_template_part( 'loop' ); ?>
Really simple, right? Suppose you wanted to separate files for specific types of loops or just allow child theme users to overwrite specific types of loops. The code example below will attempt to load the
loop-home.php file and fall back to the
loop.php template if it doesn’t exist.
<?php get_template_part( 'loop', 'home' ); ?>
The grandaddy of template-loading functions
The functions shown above have one thing in common: they use the
locate_template() function to load the template. This function does all the hard work of loading templates:
- Uses the correct theme directory path.
- Checks if a file exists before trying to load it.
- Allows child themes to overwrite parent theme templates.
WordPress uses this function internally for loading all sorts of templates. Theme developers should be using it when needed too. Although the functions covered earlier are great, there are some things you simply can’t do with them. You should instead use the
locate_template() function under certain conditions:
- If no other template function handles the functionality needed. Always use a more specific template function if it does what you need and is within the function's scope.
- When you need to load files from sub-folders within your theme.
- When you have more than two possible templates that could be loaded.
locate_template() function takes in three parameters.
locate_template( $template_names, $load = false, $require_once = true );
$template_names: An array of templates to search for. The first template found from the array within the child or parent theme is the "located" template. The templates should be added to the array in the order they should be searched for. This parameter is required.
$load: Whether WordPress should automatically load the template. By default, this is set to
falseand will return the template file name and path if found. If you set it to
true, the template will be loaded.
$require_once: Whether to only load the template once. By default, this parameter is set to
true. If the template might need to be loaded more than once, set this to
Let’s revisit the
loop.php idea discussed in the previous section. Suppose you wanted a more hierarchical template load order than what the
get_template_part() function provides. For example, in your theme’s
category.php file, you might want to allow for a search for these loop templates (in this order):
locate_template() function is perfect for this.
<?php locate_template( array( 'loop-category.php', 'loop-archive.php', 'loop.php' ), true, false ); ?>
One big difference here from other functions is that you directly input the entire file name. It also allows you to search for templates within sub-folders. For example, you could search for
loop/category.php if you wanted.
Getting theme templates right
The biggest thing to keep in mind is the difference between loading a template and a functions file. Always make sure to load templates with one of the template functions so that child themes can overwrite them. Never use template functions for loading a functions-type file because you don’t want child themes to overwrite them (use a require/include function).
Some of you may have noticed that I didn’t cover the major templates like
single.php, and so on. This is because WordPress loads these templates. The purpose of this tutorial was to cover code that’s used within themes. I’ll save the WordPress template hierarchy for another day.
I hope this tutorial has been helpful to theme developers. Keeping up with the appropriate functions can sometimes be a tough task. Even I’ve made mistakes in this area. If you just use the available functions, you’ll be safe and your theme will be forward compatible with future versions of WordPress.