Reusing Template Files

WordPress’ built-in template hierarchy is very useful for reusing template files on standard websites. If you have something you want used for all category archives, use category.php. If you want a template file to be used on all archives (category, tag, search…), use archive.php.

But when you’re building websites with complex content structures, you’ll often need to build a very specific template hierarchy of your own, or else duplicate a lot of code.

I’m building a site right now with four custom post types, and each post type has 2-4 taxonomies. Take a look at the screenshot above. The ‘recipe’ post type has two taxonomies: ‘name-range’ which allows the client to break down the list of recipes by name (ex: A-D, E-G…), and ‘base’ (dropdown says category), which is a shared taxonomy with another post type that specifies the alcoholic base of the cocktail.

I want a single template file that is used in all of these situations:

  • Recipe post type archive
  • Name Range taxonomy archive
  • Base taxonomy archive (if post type is also ‘recipe’)

For this, I’ll use the template_include filter. This filter runs right after WordPress determines what template it thinks it should use, but before that template is actually loaded. This is where you can hop in and specify your own template hierarchy.

Without this technique, I’d need to put the same code in archive-recipe.php, taxononomy-name-range.php, and taxonomy-base.php (with some extra code in here to check for the current post type).

The code above says “if this is the post type archive for ‘recipe’, the taxonomy archive ‘name-range’, or the taxonomy archive ‘base’ AND post type ‘recipe’, then use the template file archive-recipe.php.”

I also like to generalize this section checker into its own function so I can use it elsewhere. You might want to add a body class called ‘section-recipe’ if any of these templates are in use. Here’s how:

First I’m creating a function that returns the current section if there’s a match, and ‘false’ if there isn’t.

Then I have my template redirect function. If the current page is in a section, it loads the template ‘archive-$section’ (ex: archive-recipe.php).

Then I have my body class filter. If the current page is in a section, it adds the body class ‘section-$section’ (ex: ‘section-recipe’ ).

If you add a new taxonomy, just edit the be_return_archive_section() function to specify the section it belongs in, and it will automatically use the correct template file and have the body class.

chat9 Comments

  1. GaryJ says

    Could you not put common code into another file, and then have a simple require in the template files that need to make use of them?

    • Bill Erickson says

      Yes, but then you’d still need to create three template files which all include a require statement. This is a much cleaner solution, assuming they are all the same template. If you only want to include a few functions, then yes, a require is best, or include the function in functions.php and just put the add_action() in the template file.

Leave a Reply

If you'd like to include code in your post, please post it to http://gist.github.com and include a link.