When you're building a WordPress theme, it's worth taking some time to identify where you can avoid repetition of code. This gives you quite a few benefits:
- You'll only have to write the code once, making you more efficient.
- If you come to edit the code in future, you'll only have to do it once.
- Anyone else working with your theme won't get confused by multiple iterations of the same piece of code.
- Your theme will have less code, which can give performance benefits.
In my experience, the most important of these points is the second one: when I've had to edit themes for whatever reason, the task is made much easier if each piece of code is only in there once.
In this tutorial, I'll show you some of the ways you can adopt the Don't Repeat Yourself, or DRY, principle in your theme development, making yourself more efficient and less stressed in the process.
What's not to like?
1. Using Frameworks and Starter Themes
Using a framework, either a third-party one or one that you develop yourself, means that a lot of the code you need will already be there for you when you start, and that you won't find yourself writing the same code again and again (or even at all).
How much code you need in your framework will be up to you—you may prefer to use a barebones framework which you then add to, or a more comprehensive one from which you select functionality for your project.
As well as frameworks, there are an increasing number of starter themes available to help speed up your coding. Currently, the most commonly used is the _s theme, which gives you the bare bones you need to quickly create WordPress themes.
Alternatively, you might prefer to create your own starter themes which include the basic code you use time and again on projects, You might create one simple one which you add to, or a number of different versions for different types of project.
2. Using Template Parts
You'll get the most bang for your buck in terms of DRY theming if you make use of template parts. The most obvious of these are the header, footer, and sidebar files, but you can also make use of loop files and other template parts to make your code more efficient.
The Header, Sidebar, and Footer
Hopefully you don't need me to tell you this—you should ALWAYS be using separate template files for your header (header.php
), sidebar (sidebar.php
), and footer (footer.php
). You then call these in each of your template files using these template tags:
get_header()
get_sidebar()
get_footer()
But you didn't need me to tell you that, so let's move on to more advanced use of template parts.
Multiple Headers, Sidebars, or Footers
Occasionally you might want to use a different header, sidebar, or footer for different areas in your site. You can do this easily, by creating multiple files.
For example, let's say you want to use a different sidebar on your archive pages. You would create a file for this sidebar called sidebar-archive.php
. In your archive.php
template file, you would then replace the standard get_sidebar()
tag with get_sidebar( 'archive')
.
This gives you the flexibility of having an additional sidebar, which you can then use in multiple template files. For example, you might want to use it in the archive templates for specific post types. So if you had a post type called button
, you would create an archive template for it called archive-button.php
, and in that you would use the get_sidebar( 'archive' )
tag.
There are some disadvantages to this approach: If your sidebar.php
and sidebar-archive.php
files have a lot of repetitive code, your theme isn't following the DRY principle closely enough. If this is the case, you might choose to use conditional tags instead, which I'll cover later in this tutorial.
Other Template Parts
As well as template parts for the header, footer, and sidebar, you can also create other template parts. You then call these template parts using the get_template_part()
tag.
The most common use of this is for the loop. The loop is a chunk of code often repeated in multiple templates, so it makes sense to take it out of each of those templates and put it in a file of its own.
To do this, you create a file called loop.php
with the code for your loop and then you call it using get_template_part ( 'loop' )
. This effectively pulls all of the code from your loop file into your template.
You can take this further with multiple loops. For example if you had a slightly different loop for archives, you would create a file called loop-archive.php
and call it using get_template_part( 'loop', 'archive' )
. Simple!
3. Using Conditional Tags
Sometimes it's more efficient to use conditional tags in place of separate template files. WordPress comes with a set of conditional tags you can use to check which content type is being viewed at a given time or which page template is being used. So you can use them to check if a specific template is being used and then add some code if it is. This saves you creating an extra template file if your template files have a lot of duplicated code.
I'll illustrate this with an example. Let's say you have a sidebar with a widget area registered. On the single pages for a given post type, you want to add a second widget area. You might want to do this if you want to list other posts of that post type in a widget, for example.
You could create a separate sidebar file called sidebar-xxx.php
, where xxx
is your post type, and then call that in the template file for your post type. Or you could just use one sidebar file with a conditional tag to add the extra widget area as follows:
In your sidebar.php
file, you will already have a widget area registered, which might look something like this:
<?php if ( is_active_sidebar( 'sidebar-widget-area' ) ) { ?> <aside class="sidebar widget-area role="complementary"> <?php dynamic_sidebar( 'sidebar-widget-area' ); ?> </aside> <?php } ?>
This will display the sidebar widget area if it has been populated with widgets.
You can then add a second sidebar using the is_singular()
conditional tag:
if ( is_singular ( 'xxx' ) && is_active_sidebar( 'xxx-sidebar-widget-area' ) ) { ?> <aside class="sidebar xxx widget-area" role="complementary"> <?php dynamic_sidebar( 'xxx-sidebar-widget-area' ); ?> </aside> <?php }
This checks to see if the widget area is populated in the same way as the first example but adds an extra check to that if
statement: is_singular( 'xxx' )
. This checks if the site is currently displaying a single page for the xxx
post type. If that's the case and the widget area is populated, then it will be displayed.
4. Turning Repetitive Code Into a Function
If your code will be repeated again and again throughout the site and it doesn't lend itself to being put into an include file of its own, then another solution is to put it in a function and then call that function wherever in your template you want the code to appear.
For example, you might have some code to display a call to action box:
<section class="cta"> // CTA content goes here </section>
Repeating the same code in multiple places in your theme would be bad practice, as it would add extra code and make it very difficult for you to accurately amend the code if you needed to in the future. Instead you could wrap it in a function, and then place that function in relevant places in your theme.
Your function would look like this:
function wptp_cta() { ?> <section class="cta"> // CTA content goes here </section> <?php }
Then if you needed your call to action box to appear in places in your theme such as sidebars or footers, you would just write the function in the relevant template file:
wptp_cta();
The great advantage of this is that if you want to change the call to action in the future, you only need to change the function once and the change will be reflected everywhere you've called it in your theme.
5. Hooking Code to Action Hooks
The next step up in DRY theme development is to make use of action hooks in your theme.
You create an action hook using the do_action()
function, and then you attach functions to that hook using add_action()
.
This gives you much more flexibility in how you use your recurring code, and allows you to specify not only where in your theme it will appear but in what circumstances, using a combination of functions and conditional tags.
It also means that if you're creating child themes using your original theme as a parent theme, you can attach functions in your child theme to the function from the parent theme.
I'll return to my sidebar example. Instead of coding the widget area into my sidebar.php
file, I just add an action to it, giving it a unique name:
do_action( 'wptp_sidebar' );
This creates an action hook in my theme, to which I can attach custom functions.
In my functions.php
file, I then hook the code for the standard sidebar to this action as follows:
function wptp_sidebar_default() { if ( is_active_sidebar( 'sidebar-widget-area' ) ) { ?> <aside class="sidebar widget-area" role="complementary"> <?php dynamic_sidebar( 'sidebar-widget-area' ); ?> </aside> <?php } } add_action( 'wptp_sidebar', 'wptp_sidebar_default' ););
I've used add_action()
with two parameters: wptp_sidebar
, the name of the hook, and wptp_sidebar_default
, the name of the function.
So that's the standard sidebar added to my theme. To add the sidebar for my post type, I add a second function to my functions.php
file and hook it to the same action hook:
function wptp_xxx_sidebar() { if ( is_singular ( 'xxx' ) && is_active_sidebar( 'xxx-sidebar-widget-area' ) ) { ?> <aside class="sidebar xxx widget-area" role="complementary"> <?php dynamic_sidebar( 'xxx-sidebar-widget-area' ); ?> </aside> <?php } } add_action( 'wptp_sidebar', 'wptp_xxx_sidebar', 15 );
This wraps my second sidebar in a function and then fires that function on the wptp_sidebar
action hook as well. A couple of things to note:
- The conditional tag goes inside the function and not with the
add_action
function. - I've added a priority of
15
to my second function. As the default priority (which will have been assigned to my first function) is 10, this means that WordPress will fire this second function after that first one, so thexxx
sidebar will appear below the default one.
Summary
The ideas I've covered above aren't an exhaustive list of methods for adopting the DRY principle when developing WordPress themes, but they give an introduction to some of the most effective methods you can use.
If you want to ensure your themes are as efficient as possible, I would advise taking time to plan your theme's structure before you start writing code. Identify where code will be duplicated and which approach would be best for preventing repetition of code and effort. Work your way through the ideas above, using the one which will save you the most time and code. This will help you develop the theme further in the future.
Comments