2

Say I have a plugin which fires the plugin_1_action when it initializes.

Now, because I wanna extend that plugin, I'll hook into plugin_1_action, but what if my plugin was installed after that plugin? Won't that plugin run first and so, I'll lose the chance to catch the plugin_1_action hook?

It's just weird and magical to me that I can, no matter what, hook into, say, Woo's actions and Woo can hook into mine, even if clearly my plugin has been installed later than it.

Even if most plugins run on the init hook (so they get executed on the same space), they still have priorities set differently. Meaning that plugin1's code will run before plugin2's code and if plugin2 has a hook into plugin1, well, tough luck...or not, apparently WordPress doesn't have this issue.

How does it work?

  • 1
    Note that the order plugins are installed or activated in the past has no bearing on the order they are loaded in. WP does not track that information, a plugin is active or it isn't, they're always loaded alphabetically – Tom J Nowell Jul 30 '18 at 4:17
  • 1
    Also, hooks are like events, I can tell you to put the kettle on when the date is 1January 2000, and you'll understand but it won't happen, it's too late. The same is true of hooks. Think of them more as events and things will make more sense. – Tom J Nowell Jul 30 '18 at 4:21
3

If the plugin indeed runs plugin_1_action as soon as it's loaded, meaning that the do_action() call is just sitting in the plugin file and not inside a function that's hooked later, then yes, you're correct: you won't be able to hook into it if your plugin is loaded later.

This is almost never how plugins work though. Pretty much all plugins won't actually run any code as soon as they're loaded. Plugins will typically hook all their functionality to occur later, usually no earlier than the init hook, which is run after all plugins and themes have loaded.

So let's say the original plugin has this code:

function og_plugin_initialize() {
    // Does stuff.

    do_action( 'og_plugin_initialized' );
}

This code will probably be hooked to run on the init hook:

add_action( 'init', 'og_plugin_initialize', 20 );

So the og_plugin_initialized hook won't be executed until the init hook, at priority 20.

If you had a function that you wanted to hook into the og_plugin_initialized hook, then you would add it in your plugin like this:

function my_plugin_init() {
    // Do stuff.
}
add_action( 'og_plugin_initialized', 'my_plugin_init' );

When it's done like this it doesn't matter which order the plugins load in, because both plugins and queued up their functions to run later. And since both those functions will run after all plugins have loaded, you can use functions defined in the original plugin without issue.

2

Important: Think of actions and hooks instead as events

That mental model will serve you far better.

Now, because I wanna extend that plugin, I'll hook into plugin_1_action, but what if my plugin was installed after that plugin?

You can install your plugins in any order you want, they are all loaded in the same order regardless. Installing plugin C first doesn't mean its code runs first.

Plugins are loaded alphabetically, so plugin a will load before plugin b because A comes before B, etc

Won't that plugin run first and so, I'll lose the chance to catch the plugin_1_action hook?

Correct, if the action is fired once, and that event has already occurred, then it's too late. You can still hook into it, but that event has already happened, so it will never run.

Similar to telling somebody to buy milk after they've been to the shop rather than before. You can do it, but it won't get you milk unless they visit the shop a second time.

For it to still work would need to involve some kind of time travel/temporal mechanics. Dr Who might be able to do it, but we'll require refactoring to fix the original plugin.

It's just weird and magical to me that I can, no matter what, hook into, say, Woo's actions and Woo can hook into mine,

Actions are just actions, they don't belong to anybody. There's no sandboxing of code, and once it's loaded it's loaded. A plugins code shares all the same space as WP Core, and other plugins.

even if clearly my plugin has been installed later than it.

Installation order is irrelevant. As we learnt earlier too, order of execution matters, once the event/action/hook is fired, you can still hook into it, but your functions won't run until it's fired again which might never happen. WP hooks don't do time travel.

Even if most plugins run on the init hook (so they get executed on the same space), they still have priorities set differently.

Indeed, if the event hasn't happened yet, you can indicate priority to influence the order the functions are called in.

Meaning that plugin1's code will run before plugin2's code and if plugin2 has a hook into plugin1, well, tough luck...or not, apparently WordPress doesn't have this issue.

Oh but it does! As I mentioned earlier, you can add functions to a hook that has already fired, that doesn't mean it retroactively applies it to previous times the hook fired. As I mentioned before, that would require time travel technology.

The root problem here is that the plugin is doing work before the init or admin_init hooks happen. When plugins load, they should set up their objects, add their hooks etc, but they shouldn't do work. That's what the lifecycle events of init etc are for

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.