Introduction to Custom Hooks and Pluggable Functions


If you’ve read through part 1 of our introduction to WordPress Hooks, you should be well aware of what constitutes an “action” or “filter” hook and where they can be used. Today we’ll be exploring a little further down the rabbit hole, as we discuss pluggable functions and the concept of creating our own “action” and “filter” hook points, as well as how we can leverage these and create relationships between themes and plugins using various WordPress Hooks.

Note: This tutorial isn’t for the faint of heart (there are a few advanced bits). If you haven’t read part 1, I strongly suggest doing so before reading on.

What are custom action and filter points?

As we discussed previously, it’s possible to use actions to run your own code at key points during a WordPress page load, as well as using filters to modify text, settings or just about anything with a filter on it, to tailor your WordPress installation to be exactly as you’d like it. What about themes and plugins though? How do I inject my own custom goodness in there? That’s where custom action and filter points come in.

Using the same functionality built within the WordPress core itself, we can create our own action points (such as `wp_head` or `wp_footer`) within our themes and plugins. This is, at it’s core, relatively straight forward and can be used in either a standard or a more advanced way. Assuming we’re working on a plugin called, for example, “WPCandy News”, we could add the following to the top of, say, a widget that displays the latest news:

<?php do_action( 'wpcandy_news_widget_before' ); ?>

This is the core of what makes up a WordPress action point. The do_action() function instructs WordPress to look for any hooks attached to whatever tag is specified (in our case, that would be “wpcandy_news_widget_before”) and run that function. Simple, right?

Hold on a moment, that’s not all. The `do_action()` function can also accept multiple arguments (parameters) which are then passed through, if desired, to the function we’re hooking on. Sounds complicated, right? Not really. Let’s use the same example above, but extend it a bit.

<?php do_action( 'wpcandy_news_widget_before', $limit, $id ); ?>

To the snippet, I’ve added 2 extra arguments; a `$limit` variable and an `$id` variable. These are example variables that would be created by the plugin, holding the number of articles to display and the ID we’re assigning to an element in the widget respectively. If we setup our `add_action()` call correctly, we should receive these values in our function, ready for us to use.

Hold on, where does add_action() come into this?

Without add_action(), `do_action()` means nothing. The `add_action()` function allows us, and other themes or plugins, to assign functions to be run when WordPress reaches our action. At it’s core, an example of how we’d hook onto our new action point would be:

<?php add_action( 'wpcandy_news_widget_before', 'wpcandy_news_widget_before_content' ); 
function wpcandy_news_widget_before_content () { 
     echo '<p>' . __( ' This is our custom text.', 'wpcandy' ) . </p>'; 
} // End wpcandy_news_widget_before_content() ?>

Now that’s great and all, but what about `$limit` and $id`? Enter our last two parameters; the “priority” and the “accepted arguments”.

Priority allows us to optionally specify an ordering for when our action should be executed, if multiple actions are assigned to the same `do_action()` call. This can be extremely useful in controlling the flow of your theme or plugin. Additionally, the accepted arguments number allows us to optionally specify that multiple arguments will be passed through to our action. The default value is 1, so no need to specify anything if you only have 1 argument going through.

This is what our modified code would look like:

<?php add_action( 'wpcandy_news_widget_before', 'wpcandy_news_widget_before_content', 1, 2 ); 
function wpcandy_news_widget_before_content ( $limit, $id ) { 
     if ( $limit > 5 ) { 
          echo '<p>' . __( ' This is our custom text.', 'wpcandy' ) . </p>'; 
} // End wpcandy_news_widget_before_content() ?>

We’ve made several minor changes here, which are as follows:

  1. Added the “priority” and “accepted arguments” parameter values, set at 1 and 2 respectively.
  2. Added `$limit` and `$id` values to our function, to be passed through by `do_action()`.
  3. Made example use of our `$limit` variable inside the function.

Often, for scalability’s sake and keeping things clean and future proof, developers often encase these `do_action()` calls within functions. An example of this would be the `wp_head()` function, added to the vast majority of WordPress themes (so much so, that it is deemed a requirement). This function, in essence, runs `do_action( ‘wp_head’ )`, which is as straight forward as explained above. Magical, right?

Okay, but what about filters?

The concept of custom filter points is much the same as for custom action points, except it relates to filters. As we discussed in part 1, it’s possible to place a filter on just about anything, from a snippet of content to an array of settings or options. The requirements here are much the same as with `do_action()`, except for two aspects; the first being that we’re using the `apply_filters()` function and the second being that we require two parameters instead of just the tag. The second parameter involved is the core of what makes the `apply_filters()` function necessary- the data itself.

Lets dive right into an example of how we’d put this into action. Continuing the example of our “WPCandy News” plugin, lets place a filter on our widget’s title. The code for this would look as follows:

<?php $title = apply_filters( 'widget_title', $title ); ?>

This code says; “take the value of the `$title` variable, apply any filters attached to the ‘widget_title’ hook, and assign the filtered value back to the `$title` variable”. Simple, right?

If you’re familiar with PHP, a basic comparison I like to make when explaining how filters work is to compare them to string-related functions in PHP such as `str_replace()`. We’d use the `str_replace()` function in a much similar to way our snippet above, as follows:

<?php $title = str_replace( 'one', 'two', $title ); ?>

The concept is that we’re passing a value through to our function and getting a value back. This is the core of what a filter function does.

Much like `do_action()`, the `apply_filters()` function can also accept additional arguments. These function in exactly the same way as with `do_action()` and are made available using the “priority” and “accepted arguments” parameters on the `add_filter()` function, in the same way as they are used on `add_action()`. As can be seen, the differences between “action” and “filter” hooks and how they are created is marginal (they both function off of the same backbone code).

Even if you don’t intend to create your own action and filter points, it’s important to understand the full scope of how they work and how the `add_action()` and `add_filter()` functions fit into the grand scheme of things. If you use themes such as Canvas, for example, you’ll notice these types of custom hooks in use, which are there to allow maximum flexibility and control over the way you’d like the theme to display and function.

Enough about hooks, what are these “pluggable function” things?

The concept of a “pluggable function” has become popular within the WordPress community, particularly in the realm of parent themes and theme frameworks. These are functions that are overrideable by simply creating a new instance of the function within a child theme or in a part of the theme that’s triggered before the function’s original location (this is commonly the root of the `functions.php` file). This concept is option used for functions that generate commonly customised areas of themes, such as the post metadata below the title on a theme’s blog posts archives, or the area below the post content on single blog post screens. As with “action” and “filter” hooks, there are virtually infinite uses for pluggable functions.

Okay, I get it. How do I create these?

This part is really simple. It involves two skills; the first being knowing which functions in a theme are pluggable (and therefore, knowing the theme) and the second being knowing how to make the modification you’d like to make.

An easy way of finding out which functions in a theme are pluggable is by searching for the following code:

if ( ! function_exists( 'insert_function_name_here' ) ) {

This line is the beginning of a conditional statement that would commonly wrap around a function with the name “insert_function_name_here”. This just says that the function should only be created if it doesn’t already exist, which leaves room for the function to be overridden. Lets create an example of this.

This would be our original function, with the conditional statement wrapping around it:

<?php if ( ! function_exists( 'wpcandy_display_recent_news' ) ) { 
     function wpcandy_display_recent_news ( $limit = 5 ) { 
          // This is where we'd run the meat of the function. 
     } // End wpcandy_display_recent_news() 
} ?>

Overriding this in our child theme is as simple as copying the code and removing the conditional statement (the first line and the bracket at the end), and placing this in our child theme, where we can then make any modifications to it that we desire, without needing to modify the parent theme.

Hooks and pluggable functions are great, but when do I use which?

A general rule of thumb that I like to stick to is: a function should only be made pluggable if not attached to an “action” or “filter” hook. The reason for this is that it’s possible to remove functions from hooks, as well as to override them using the “priority” setting explained above, which renders the pluggable nature of the function redundant. This also makes it easier to decipher the nature of a function (if it’s pluggable, it’s not attached to a hook), which can speed up development time as well as making it easier for developers who are looking at the code for the first time to decipher what’s going on under the hood.

And that, ladies and gentlemen, is a tutorial on how to create your own action and filter points, as well as a brief introduction into the concept of pluggable functions, how to use them and when to use which techniques.

6 thoughts on “Introduction to Custom Hooks and Pluggable Functions

  1. a function should only be made pluggable if not attached to an “action” or “filter” hook

    Now I finally understand why every single function in canvas is not pluggable. Great tutorial..

    • Thanks Shawn. 🙂
      Yeah, while it is possible to have every function pluggable, it isn’t always necessary, as it could be overridden via the action/filter, or simply removed via remove_action() or remove_filter().

Comments are closed.