Does it matter if a hook’s callback function comes before or after its add_action
? My answer might surprise you. No, it does not matter to PHP or WordPress. Yes, it does matter for code readability. I’ll explain why in this article.
A member asked me if the order matters when registering a function to an action hook? Should the order be:
- function and then
add_action()
… OR add_action()
and then the function
For example, let’s look at the Twenty Seventeen theme’s functions.php
file and the very first function in that file. It’s structured like this, where the function is declared on line 27 but the add_action
is on the first line after the function, i.e. all the way down on line 225.
/** * Sets up theme defaults and registers support for various WordPress features. * * Note that this function is hooked into the after_setup_theme hook, which * runs before the init hook. The init hook is too late for some features, such * as indicating support for post thumbnails. */ function twentyseventeen_setup() { // the code goes here }
add_action( 'after_setup_theme', 'twentyseventeen_setup' );
Does PHP or WordPress Care Which Comes First?
No, neither PHP or WordPress care if the function comes first or the add_action
. Let’s talk about why.
Reason 1 – PHP lets you.
Technically, PHP will let you call a function before its declared in the same file. For example, you could do this:
twentyseventeen_setup(); function twentyseventeen_setup() { // the code goes here }
That’s perfectly valid code. Even though the function is being called before it’s declared, PHP lets you do this. But this is a really bad practice. Why?
- It’s less readable. It will confuse you or anyone else who reads this code as you’ll stop and think “Why in the heck is this here?”
- It’s much, much more slower as PHP has to do some extra work to generate OPCodes at runtime.
Reason 2 – The callback will not run until the hook fires
The function will not run until WordPress fires the 'after_setup_theme'
hook. That happens after this file is loaded into memory.
Bottom line: Neither WordPress nor PHP care if the function goes first or the add_action
.
Since neither cares, then that eliminates the argument of execution order to justify putting the add_action
after the function.
Yes, the order matters for readability (code quality)
Listen Up: Readability Matters!
I dare say that it’s as important as getting your code to work. Why? Because readable code makes it so much easier for you or anyone else to quickly pop into a file, figure out what’s on going, and do your work. It makes it easier to find bugs as well as reuse and extend your code. It’s a vital component to your job! It matters.
The code above is less readable. Having the add_action
comes after the function is less readable. Why?
Because we read from the top down. Right? When you open a book, you don’t start at the bottom of the page and read it backwards to the top. Nope, you start at the top and read down. That’s the same in code.
When the function appears first, it’s not communicating that “Hey, I’m a callback and I’m registered to this hook.” Nope, you have to scroll down the file and then find where it gets hooked.
A better practice and the one that I recommend is to have the add_action
first and then the function. That is more readable. You can more quickly read and understand what’s going on and that the function is registered to that hook. It will save you time.
Let’s refactor the code:
add_action( 'after_setup_theme', 'twentyseventeen_setup' ); /** * Sets up theme defaults and registers support for various WordPress features. * * Note that this function is hooked into the after_setup_theme hook, which * runs before the init hook. The init hook is too late for some features, such * as indicating support for post thumbnails. */ function twentyseventeen_setup() { // the code goes here }
Read the above code. On line 20, it is telling you “Hey, this is an action, the event’s name is 'after_setup_theme'
, the function is twentyseventeen_setup
, the priority is 10. It’s clear and descriptive. The above code does not need a comment to tell you that it’s hooked to that event. Nope, you can quickly see that it is.
Mike Schinkel says
An even better practice is to say no to declaring hook functions while running in the global function namespace and instead create classes that group related hooks. Then have an on_load() method (or initialize()) that adds hooks with the hooks being methods of the class.
Tonya Mork says
Hey Mike,
A class is also in global namespace, i.e. same as a function, unless we use PHP namespacing (which I advocate using).
Yes, your design is my approach too when using OOP. But for procedural, I advocate placing the hook before its associated callback.
Cheers,
Tonya