Using WordPress Hooks Differently

Using WordPress hooks is one of those topics that you hang around any Slack channel forum, email thread, Twitter conversation, or whatever and you’ll find that understanding them and using them correctly is key to working with the application.

Using WordPress Hooks

But if there’s one thing that I get obsessive about, is using the right hook (as opposed to the left hook 🙃).

Sure, that reads weird, but look at it this way:

  • each hook offers a variety of parts of the application available at a given time,
  • and each hook is given a specific name.

So it would stand to reason that we try to hook our functions into the hook that’s most closely aligned and appropriately named for our particular requirement, right?

Using WordPress Hooks (But Differently)

For example, let’s say that I’m working on a plugin that’s obviously going to be using WordPress hooks and I’ve got a file that kick-starts the whole process (namely, a bootstrap file). I typically attach this to plugins_loaded and then I let the plugin do its thing.

This satisfies both requirements above:

  • the plugin is attached to WordPress at a time where the necessary resources are available,
  • the plugin is attached to a hook with a name that makes sense.

What happens, though, whenever we’re working on a plugin that needs resources later in the application, earlier in the application, or simply need something that isn’t available when plugins_loaded fires.

What then?

Personally, I get a bit obsessive about how I set up my plugins so having to using WordPress hooks differently than I’d like for my initial function irritates me. I feel like it creates less-clean code in that it doesn’t read as well.

What do you mean, you’re starting this function with wp_loaded? Wouldn’t this always work with wp_loaded?

Maybe that’s a bad example but you get my point.

And sure, there are strategies initialize components at different points in the WordPress lifecycle and then have them work altogether, but that’s more advanced than the purpose of this post.

What’s the Point of This?

All I’m trying to say is that if you’re someone who tries to align bootstrapping their plugin with a hook that’s at the best possibly time in WordPress’ execution and creates the cleanest code, accept that sometimes using different WordPress hooks are a nature of working with the application.

Sometimes, certain features or components just aren’t ready for when your plugin needs them. So you’re left with either trying to execute a plugin prematurely, or using a hook that may lack a name of clarity but has the resources you need.

And the worst case scenario? You document what you’re doing in the code comments.

4 Replies to “Using WordPress Hooks Differently”

  1. Hey Tom,

    I’m sure you know that feeling when your “perfect hook” just turns out to not be usable for the right optimization.

    I sometimes need to use two, three or four different hooks to be able to only load what is strictly needed at every point in time, just because the first available hook does not yet have all of the information my plugin needs to decide whether it should be completely loaded or not…

    I’m always pretty frustrated by stuff like that. Clean, elegant code is mostly gone at that point… ;) But I find it even worse when just blindly loading all sorts of code and assets if it would be clear it is not needed.

    Cheers,

    Alain

    1. I’m sure you know that feeling when your “perfect hook” just turns out to not be usable for the right optimization.

      Ugh — yes. I know, I know it’s not so much about what it’s called but what resources are available to us, but some hooks, when reading code, just don’t always read as cleanly as others. And that can cause a trip up like “Why this hook?”

      It’s only over time, I think, that one begins to understand “Oh, they must have needed something that wasn’t available until earlier.”

      I sometimes need to use two, three or four different hooks to be able to only load what is strictly needed at every point in time, just because the first available hook does not yet have all of the information my plugin needs to decide whether it should be completely loaded or not…

      I need to experiment with this.

      But it raises a question for me: If you’re using a DI container, how early do you initialize it and then at what level? (Do you have a gist?) I mean, it’s gotta be at a level that’s accessible everywhere which, to me, says it’s some type of singleton (which I doubt, knowing you) or it’s stored somewhere at a level that accessible no matter where you are in the lifecycle.

      Super curious about this.

      Clean, elegant code is mostly gone at that point… ;) But I find it even worse when just blindly loading all sorts of code and assets if it would be clear it is not needed.

      Ah, maybe not mostly. But a little at least ;).

      But yes, I’m refactoring a plugin now for someone and it’s going super well because I get a chance to being tearing pieces out of one monolithic function into places where it really does belong.

      1. It’s only over time, I think, that one begins to understand “Oh, they must have needed something that wasn’t available until earlier.”

        Yes, and when I started experimenting with WordPress hooks, I found it frustrating that it was not always immediately obvious how many times a specific hook will get called, which lead to all sorts of weird behaviour… ;)

        If you’re using a DI container, how early do you initialize it and then at what level?

        Well, this obviously only applies when working on an entire site architecture, not a single public plugin…

        I do actually use two different DICs. I have one DIC that is managing the “inter-plugin” level, which is my service locator, and I have one DIC that is managing the “intra-plugin” level, which is my actual dependency injector.

        I have done this clear separation because the service locator is often called out as an anti-pattern, simply because people completely abuse it in all sorts of wrong ways. And, although there’s not a lot of technical difference between a service locator and a dependency injector (which makes above abuse so easy and common), there’s a huge conceptual difference between the two.

        Both of these are defined in a must-use plugin, so that they are available to all normal plugins from the moment they are loaded. The service locator also contains its own dependency resolution mechanism, so that plugin loading order becomes irrelevant.

        So, when a plugin needs to use a dependency (which is then called a service) from another plugin, it asks the service locator for an instance of that service. This causes the plugins to not be tightly coupled through code. All that one plugin knows about another one is a specific service identifier it needs to ask. And the dependency resolution I managed before makes it so that, in the case where that service is not available, the plugin will stay enqueued but will never get activated, avoiding a fatal error.

        When a plugin needs a dependency from a different part of itself, the real dependency injector comes into play. So, for example, if the EmailNotification class needs an EmailSender to do the actual sending, it just includes the corresponding interface within its constructor. As the entire plugin is actually instantiated through the auto-wiring dependency injector, the injector will see that the EmailNotificationhas in its constructor something like the following: public function __construct( EmailSenderInterface $sender ); and look within its configuration to see what class to instantiate to pass into that constructor. And the config also tells it whether that instance is shared, or whether it needs to always instantiate a new instance. So, there’s practically no new XXX() in my code, and no tight coupling. Everything is resolved at runtime, and can be easily changed without breaking anything.

        it’s some type of singleton (which I doubt, knowing you)

        You’re right, I personally would ban the singleton pattern, because it is just a procedural hack.

        The service locator is the only thing that needs to be globally accessible throughout all plugins. But it is a normal class, that can be instantiated as often as you want (or mocked in tests, etc…). But, I use a static facade that acts as a factory for retrieving an instance and acting upon it, and that factory happens to always return the same shared instance. So, I get the same usefulness that people use the singleton pattern for, but without all the drawbacks.

        The static facade is called Services and has a few convenience functions to make working with it easier. So, you have a Services::get( 'service_you_need' ); that you can call just as if Services was a singleton. However, behind the scenes, the instance that Services refers to is instantiated through the actual dependency injector that can be configured through config files.

        Do you have a gist?

        I have not yet made the overarching architecture public (still needs some fine-tuning to be composerable), but some of the parts are available, like the service-locator (https://github.com/brightnucleus/service-locator) and the dependency injector (https://github.com/brightnucleus/injector). The plan is to make the entire architecture public, though, it just needs a bit more polish.

        1. Yes, and when I started experimenting with WordPress hooks, I found it frustrating that it was not always immediately obvious how many times a specific hook will get called, which lead to all sorts of weird behaviour… ;)

          Yes — understanding the order is one thing, understanding how many times it might be called is another (I remember having this issue with save_post and I’m not talking about the DOING_AJAX or anything like that, either.

          I have done this clear separation because the service locator is often called out as an anti-pattern, simply because people completely abuse it in all sorts of wrong ways.

          Meh, such is the case with a number of other patterns, though. I don’t worry about that kind of stuff anymore so long as I know that the implementation I’m doing has at least a greater degree of correctness than not :).

          Both of these are defined in a must-use plugin, so that they are available to all normal plugins from the moment they are loaded.

          Smart. I’m currently working on a project and I’m creating an OptionsManager of sorts and I’m debating whether or not to make it MU or leave it simply within the context of the current plugin.

          Right now, I’m leaving it as the latter because I’m not completely sure where I stand with where the project will go in the future. If additional plugins will be developed, then I’ll revisit it.

          You’re right, I personally would ban the singleton pattern, because it is just a procedural hack.

          We should have a debate on this at some point :). Friendly, obviously. It’s used as a procedural hack but it doesn’t have to be! I think there are valid times for it. But I digress — for now!

          …that can be configured through config files.

          Which seem to be a common theme for you. That is, it seems like you let config files drive a lot of what some of your classes do.

          The plan is to make the entire architecture public, though, it just needs a bit more polish.

          As is ever the case with any project ever. But seriously, I do appreciate the comment and the link!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.