In yesterday’s post, I talked about a WordPress plugin constructors and the rationale as to why hooks shouldn’t be in the constructor.

Though I mentioned a number of ways to handle hook registration, I didn’t bother to go into details for each of those strategies. As far as I’m concerned, they are deserving of their own article in order to provide as much detail as possible for how to set something up.

For example, one of the methods I shared stated:

  • It’s possible to create a class that maintains a registry of objects and the hooks with WordPress.

In other words, it’s about registering WordPress hooks using an object-oriented approach to decrease coupling and increase cohesion among the components in the plugin.

But what does that even mean? What are the advantage does it bring, how is it setup, and how it used?

Registering WordPress Hooks

If you’re reading this, you’re likely familiar with the WordPress hook system, the order of how they are fired, and how a function or class can register its functions with WordPress so they can perform whatever work they need to handle.

And we often see classes doing this on their own. Depending on the project, I do it myself. For those who aren’t familiar, it generally looks something like this:

But all of this can be broken up into more cohesive classes to ultimately give them classes even less responsibility (a good thing) and to decrease coupling between a class or set of classes with WordPress.

WordPress Plugin Hooks

An example of a design that I’ll break down in this post.

The counterintuitive nature of this, though, is that it will require at least one another class. But here’s how it works.

Setting It Up

For the purposes of this example, we’ll just be using a simple class that is going to register some type of action with WordPress. The idea for the architecture works something like this:

  1. There’s the main class that has the function we want to hook to WordPress.
  2. There’s a class responsible for orchestrating hooking the class’ function to WordPress.

Easy enough, right? But here’s the catch: The class responsible for registering a given class’ functions with WordPress is the point that requires a design decision.

First, let’s call the class HookRegistry so we can refer to it properly. Next, let’s call the class with the functions we want to hook AcmeColumn simply to represent a class that adds a new column the Page dashboard in the admin area of WordPress.

With that in place, the design decision comes down to this:

  1. Should the HookRegistery know about AcmeColumn?
  2. Should AcmeColumn know about the HookRegistry?

I know there are other ways to organize this and there are also strategies for how to handle this (like inversion of control) and these are topics that are worth exploring, but to keep this initial idea straightforward as possible, I’ll table that for a future post.

Using The Class

Given the options above, we’ll pass an instance of AcmeColumn into the HookRegistry when the classes are instantiated during the initial WordPress plugin startup process. This may look something like this:

Next, whenever it’s time to have AcmeColumn register its function with WordPress, we’ll call the HookRegistry and instruct it to do so.

First, AcmeColumn:

Then the HookRegistry:

Optionally, we can also maintain a list of the various classes and hooks that have been registered. This may or may not be useful depending on your implementation so I’m sharing purely as a “here’s something that you may want to do.”

And that could look like this (using a simple associative array):

Notice that in the class above, it now accepts an $id as a parameter. There are multiple ways that you can identify the information that’s going into a registry the easiest of which is to create the ID yourself.

However, if you wanted to use something like the name of the hook or the name of the class, that would work, too. Just note that since it’s an associative array, it can only maintain a single value per key, so you can end up trashing previous data if you aren’t careful.

Regardless, this is something that I consider optional, but if it’s implemented, it’s important to make sure you have the proper functions to retrieve an instance of the object by a key.

One of Many

As with anything related to this type of work, it’s possible to rearchitect or reorient this in a way that works differently or that suits your needs. The purpose isn’t to show the definitive pattern for how to do something, but a way to approach and adapt it (much like any design pattern).

Further, it’s meant to make sure that our classes maintain the responsibilities’ for which they are created all the while allowing them to register themselves with WordPress as needed. This time, though, the class doesn’t have to do that itself.

Instead, it passes the responsibility to a class that has the sole responsibility for registering said hooks. So although it introduces more classes, it increases cohesion and decreases coupling.

This offers benefits in maintenance, testing, and overall design.