Underscorefunk Design

Design, Illustration, Interaction, and Artistic Direction

Using engine rooms to create WordPress partials output runtime

Caveat: I mix a lot of metaphors here. They’re nautical in nature. πŸ™

On a ship, the engine room is literally where the engine lives–the great contraption that propels our vessel through water. For our purposes we’re going to think of engines as smaller contraptions that drive specific parts of our website. In practice they look more like a series of connections, almost more like a control room. See ‘hook.php’ below for an example of what you might find in an engine room file. This might not make a ton of sense right now but it will once you’re done reading this article.

It is worth noting that I will be presenting the engine room concept in relation to the rendering and output of a template’s content. This approach and the thinking behind it can be applied to other areas of your development as well.

The problem being solved

Traditionally I see a lot of folk with a function definition followed by the function’s hook, like this:

The problem I have with this is that you’ll often have an absolute ton of these declarations in a single file. That much code can make it difficult to see what’s really going on. Ultimately I’m going to have two different sets of needs here; I want a general overview of the course my ship is taking (the runtime of what is happening and in which order), and the ability to really look at what is going on during a specific part of the process.

If I’m editing the specific part, I don’t care about the general view. If I’m looking at the general view, I’m probably not too concerned about the minutia of a specific part. Being conscious of these different concerns will help me stay efficient.

It’s for this reason that I like to split things out. What we’re doing is:

  • Keep all runtime easy to understand in a single hooks.php engine room.
  • Keep all dispatchers that handle which output to load in separate php files.
  • Keep all output in partials and templates files.

The benefits are:

  • High level of clarity–it’s easy to see what is happening and when
  • It’s easy to inject additional content in the runtime
  • Painless incremental template customization
  • It’s very DRY (Do not Repeat Yourself)


I use this approach in object oriented development, calling the method that I named “register_hooks()” in the a plugin’s constructor.

We’re going to take a look at how our pages render and create a structure for the site though a series of actions that call partials either render output or call other actions (or both).

Here’s a quick look at a simplified file structure. Currently it only shows one sub-folder within structure called ‘singular.’ When a whole theme is built out you’d end up with sub folders for each major component. I’ll discuss my approach to implementing this for global templates like archives.php and front-page.php in a later article.

This assumes that you’re including the required php files (hooks.php, singular.php, etc) in your function.php file or somewhere else in the template.

hooks.php (structure engine room)

Our engine room is simple. It’s just a series of actions. The elegance of this is that you can easily see that theme_singular is going to call a header and then a body, and you can easily see that theme_singular_header is going to call a heading.

At this point I hope you can see how easy it would be to add another hook for a featured image banner before the theme_singular_header, or add a footer after the theme_singular_body.

singular.php (hook callback functions)

Here’s a quick look at the callback functions. I like to think of these actions as dispatchers and never put any output in them. Output isΒ always relegated to templates and partials.

I’m adding the post type name to the get_template_part request so that I can override content easily on a needs basis. For example, I can have a heading for my post type ‘book’ by creating a file in partials/singular/heading-book.php. If it exists, that file will be used. If it doesn’t exist, the default partials/singular/heading.php will be used.

I apply a filter to the post type name ($name) which receives the content in which the filter is being called. This allows me to override specific parts for specific post types. This allows me to easily modify the name by another plugin to load custom partials.Β $name doesn’t always need to be the post type name. It could be ‘book-featured’.

header.php and heading.php (component output/partial)

Sometimes the partials are micro templates of sorts, like the header.php partial. Other times they might just output content, like the heading.

header.php (a container partial)

heading.php (a partial with content)

In use

Using this set of partials would look something like this.

I don’t think it gets much more clear than that.

Use filters instead of functions

While writing code we should always be striving for clarity and consistency. As time has gone on, I’ve learned to value this over being clever. The resultant code is perhaps not as elegant, but it’s a lot more maintainable.

A lot of WordPress code I’ve seen involves something like:

Why do I think this is problematic?

  • You have to declare the default in advance.
  • There is inherent concern about if the function exists (or if the plugin is activated).
  • Creating overrides is difficult and not very clear. Each function needs to be wrapped in a ‘function_exists’ check and overrides are based on the order of declaration.
  • Changing the plugin (or initial function’s) arguments can break other plugins or implementations of the function.
  • It’s difficult to see where overrides are taking place because overrides are based on the order of declaration.

The solution

I believe using filters to get values instead of most function calls is a betters solution. The resulting code would look like this:

Some of the benefits are:

  • The default value is implied in the filter’s application.
  • The filter doesn’t care if a function is hooked into it.
  • Overrides can be added with priority instead of at run time.
  • Adding additional filter arguments doesn’t break existing implementations.
  • All functions hooked to the filter can be inspected.
  • It’s easy to see what’s happening in plugins that list all of their hooked actions in a block (an engine room of sorts).

Implementation and Extras

Here are a few things I do in implementation to make this all work nicely.

  1. When I hook the base function for a filter, I set it to priority 9, so that it runs before all of the default subsequently hooked filters would run.
  2. I make the assumption that a certain value is required to allow the hooked function to run. If it doesn’t meet this criteria, the function will assume that a hooked function ran before the default one at priority 9. This avoids double processing.
  3. I always prefix filters with my plugin’s name followed by two underscores.
  4. I build everything with OOP these days and often I’ll find myself checking the result of uf_some_plugin__get_instance against if (Β $some_plugin_obj instanceof \UF_Some_Plugin ). In this situation I instantiate the plugin as a single variable and then use the filter to get its instance instead of using static classes and singleton nightmares.

Here’s how it looks in practice.