Skip to main content

Why attention to hooks is important for a WordPress theme developer

If you are a theme developer, chances are that you know about or have heard about WordPress’ hooks and filters but are not always sure about why, when and how to use them.

Since WordPress is very forgiving about the structure of your theme, it is easy to just dump all your code into one big functions.php file that just keep on growing. This might work well for a time, but sooner or later you might run into problems.

This post is not about code structuring or how to split your file in logical chunks. Rather, it is about controlling when and where your code will be executed using hooks.

Let me give you an example.

Say that you have a bit of code that you only want to include in certain circumstances. And instead of adding that same bit of code to several page templates, you decide to include it through the functions.php using conditional logic.

Potential problem #

You might be tempted to simply use the conditional tags like you would in any page template.

if( is_category() || is_page_template('listing') ) {
    // let's do this code
}

Only writing this code straight in your functions.php file will not work. The code above needs to be wrapped in a function and attached to an action hook.

Why?

Because the code will get executed whenever the file is included. And the theme file is included before the conditionals are set.

The WordPress load order #

This all has to do with the load order of WordPress, the order in which files are included and the page request is setup. John Blackbourn has put together a super walkthrough of the initialization process of WordPress.

It’s a kind of pseudo-code writeup that goes through allt the steps taken when rendering a page. All the places where you see DO_ACTION in that walkthrough, that’s an action hook right there.

As you can see, the child theme files are included before the parent theme files, and much further down in the request part is when the global conditionals is_* are setup.

When your functions.php file is run, WordPress has no idea yet whether the request is for a page, category archive, a post or even a 404 error. Your if-statement will always be false, and the code will never be executed.

Action hooks to the rescue #

By attaching the code to an action hook you can set the code to execute at a specific time in the load order. Specifically, at a later point where the conditionals exist and your code can function properly. In this case init – which is a commonly used hook – will also not work since that is too early in the loading process.

The hook I would recommend is simply called wp. This fires after the full environment has been setup but before the page template have been requested and the actual page has started to be assembled.

How to use an action hook #

Instead of the code above, do this:

/**
* Do blah when we are on a category page or the listing page template
*/
function mythemename_categorycode() {
    if( is_category() || is_page_template('listing') ) {
        // let's do this code
    }
}
add_action( 'wp', 'mythemename_categorycode' );

You probably already use hooks #

You probably know about and use hooks already. The most obvious example that comes to mind is enqueueing your stylesheet.

/**
* Enqueue stylesheet
*/
function mythemename_styles() {
    wp_enqueue_style( 'mytheme-style', get_stylesheet_uri() );
}
add_action( 'wp_enqueue_scripts', 'mythemename_styles' );

If you look at a theme like underscores, you see that almost all the code in it’s functions.php file is wrapped in functions that are attached to different action hooks. Hooks like after_setup_theme, widgets_init and so forth. This is a very good practice.

Make it a default to use hooks #

Aim to have all your code wrapped in a function prefixed by your theme name. Attach all functions to a hook, unless they are meant to be called directly in template files.

This will prevent any unintended consequences and gives you full control over when and where your code is run.