close

Day 12: Enhance your themes with the power of hooks

Last year I wrote about the power of the WordPress Loop and this year I wanted to visit the subject of WordPress once again and take a look at another concept that has made WordPress such a brilliant platform for developers: hooks. Now this is by no means a concept unique to WordPress, but it is something that has allowed for the development of thousands of excellent plugins and the ability to manipulate WordPress without the need to go anywhere near the core code!

In this article I’m going to give you a brief overview of what hooks are and how they work, followed by a couple of examples of how you can create your own hooks for your themes or plugins. To begin with, let’s start by taking a look at the two different types of hooks: Actions and Filters.

Actions and Filters

Both types of hooks are implemented in a similar way by WordPress, even the process of creating a hook is handled by the same function – if you call the add_action() that code just calls add_filter():

// from /wp-includes/plugin.php line 359.
function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
    return add_filter($tag, $function_to_add, $priority, $accepted_args);
}

The difference however is not in how they are processed in the WordPress core, it’s in how they are used. Actions for executing code when something happens and filters are for manipulating data in some form. A better way of explaining these two would be with a couple of examples.

While there are a lot of actions used throughout the WordPress core there are two very prominent ones you should already know if you’ve ever built a WordPress theme: wp_head and wp_footer. These actions should appear in every single WordPress theme via their wrapper functions wp_head() and wp_footer() respectively. The two actions are there to be used by plugins or the WordPress core to output code into either the <head> of a page or at the very end of the <body>. When logged into WordPress the wp_footer action is used to output the admin bar to the page (and then styled to appear at the top). Along with another action you might be familiar with wp_enqueue_scripts the wp_head action is used to output any scripts and styles to the <head> of the page.

As for filters, while they are in constant use all over WordPress there is one use that should be rather familiar to you, the the_content filter. This filter is used to manipulate the main content of a post and output it in HTML. However if you take a look at the WordPress core once again you’ll see just how many filters the content goes through before it’s output to the web page:

// From wp-includes/default-filters.php line 131
add_filter( 'the_content', 'wptexturize'        );
add_filter( 'the_content', 'convert_smilies'    );
add_filter( 'the_content', 'convert_chars'      );
add_filter( 'the_content', 'wpautop'           );
add_filter( 'the_content', 'shortcode_unautop'  );
add_filter( 'the_content', 'prepend_attachment' );

And that’s just what’s in one of the WordPress core files.

To give you an idea of just how many actions and filters there are going on in WordPress you can take a look at the Action reference that shows a list of just some of the actions executed in a typical page load as well as the Filter reference showing what filters are used on what data.

Now you have a slightly better understanding of what the two types of hooks can do, let’s have a look at what you can do with them in your themes (or plugins).

Creating a custom filter

To create a custom filter you need two things, a function to do the processing and some data to process. Then there are two WordPress functions you’ll need to use to set up and process your filter, the add_filter and apply_filters functions.

The apply_filters function takes two parameters, the name of the filter you want to apply first, followed by the data you want to apply it to. To apply a filter of remove_profanities to the content for example you would do:

echo apply_filters( 'remove_profanities', get_the_content() );

Remember that because a filter manipulates data it should always return the data and never directly output it; meaning you will need to either echo out the result or save it to a variable. With the filter on the content set up, you now need to create the function to perform the filtering.

function remove_profanities_filter( $content ) {
    $content = str_replace(array('Some', 'Bad', 'Words'), '[censored]', $content);

    return $content;
}

add_filter('remove_profanities', 'remove_profanities_filter');

With that all set up, if we were to run that on say, George Carlin’s 7 Dirty Words sketch, we would end up with something like this:

There are 400,000 words in the English language and there are 7 of them you can’t say on television. What a ratio that is. 399,993 to 7. They must really be bad. They’d have to be outrageous to be separated from a group that large. All of you over here, you 7, Bad Words. That’s what they told us they were, remember? “That’s a bad word!” No bad words, bad thoughts, bad intentions, and words. You know the 7, don’t you, that you can’t say on television? “[censored], [censored], [censored], [censored], [censored], [censored], and [censored]”

Now you’ve seen how to create a quick and easy custom filter, let’s look at how to create a custom action hook.

Creating a custom action

Actions are used to perform certain tasks during the WordPress execution process or output code at certain points. For example every time you create a custom post type you’re using an action early on in the execution process to run the code and tell the WordPress admin that there’s a custom post type to create the menu item and interface for.

Creating a custom action for your themes could be useful if you need a certain point in your theme where you can execute or output code from various different functions. A lot of WordPress starter themes or parent themes will come with a series of custom hooks for you to output content or run functions against to save you from editing the core code and plugins will also often use custom actions for similar reasons. Actions are a great way of keeping your templates more maintainable and easy to read. By keeping all your functionality away from the main templates you can use hooks to make sure you’re only writing custom functionality once and applying it to as many areas as you need through hooks in your templates.

For this example you’ll look at how creating custom actions for your themes can allow you to add areas before and after the content in your pages to add elements to enhance your site’s content. For starters let’s create a basic loop, which you might see in the single.php template:

<?php if( have_posts() ): while( have_posts() ): the_post(); ?>
    <article <?php post_class(); ?>>        
        <h1><a href="<?php the_permalink(); ?>" rel="bookmark" class="entry-title"><?php the_title(); ?></a></h1>

        <div class="entry-content">
            <?php the_content(); ?>
        </div>
    </article>
<?php endwhile; endif; ?>

The hooks will be placed before and after the main content this way you can add in some extra elements such as social sharing links for instance. To do this you can use a similar method to how WordPress does by default, using wrapper functions containing the hooks.

The wrapper functions should go in your functions.php file, calling the do_action function with the name of the action.

function before_content() {
    do_action( 'before_content' );
}

function after_content() {
    do_action( 'after_content' );
}

Adding those to the loop in your template and you’ll have something like this:

<?php if( have_posts() ): while( have_posts() ): the_post(); ?>
    <article <?php post_class(); ?>>        
        <h1><a href="<?php the_permalink(); ?>" rel="bookmark" class="entry-title"><?php the_title(); ?></a></h1>

        <?php before_content(); ?>

        <div class="entry-content">
            <?php the_content(); ?>
        </div>

        <?php after_content(); ?>

    </article>
<?php endwhile; endif; ?>

Now with the hooks placed in the template file you can use the add_action function to register functions to be called at those points in the templates. To continue with the social sharing links example you could create a function that outputs the share links and add them to either of the before or after content actions to add them to the page. For example:

function add_social_sharing() {
    // Output social media links
}

add_action( 'after_content', 'add_social_sharing' );

Actions with arguments

To go one step further from this, you can also add arguments to an action. In this situation it might be useful if you wanted to add content based on the current location of the hook (which post is being displayed for instance). To do this you need to make a couple of small changes to the way you call each of the functions associated to the actions.

In the do_action function you need to pass in the argument(s) you want to use in addition to the name of the action. For the examples here this will also mean updating the wrapper functions for the actions to take an argument from where they’re called in the template. You can add any number of arguments to an action by simply passing them as extra parameters in the do_action call, like so:

do_action( 'action_name', $arg1, $arg2, $argN );

For the before and after content actions here you’re just going to add the one argument of the post ID, which will mean the wrapper functions will look something like this:

function before_content( $post_id ) {
    do_action( 'before_content', $post_id  );
}

function after_content( $post_id ) {
    do_action( 'after_content', $post_id  );
}

And when you call the wrapper functions in the template they will now need to pass in the current post ID:

<?php before_content( get_the_ID() ); ?>
<?php after_content( get_the_ID() ); ?>

The last change you need to make is to the add_action function. The full list of parameters the function can take look like this:

add_action( $tag, $function_to_add, $priority, $accepted_args );

So far you’ve only used the first two, the $tag name and $function_to_add name. To tell you action that it’s being passed arguments as well you need to use the final parameter $accepted_args as well, which means you also need to complete the $priority parameter for good measure. So now the add_action function used to add the social sharing function to the template should look like this:

add_action( 'after_content', 'add_social_sharing', 10, 1 );

At the moment the priority you use really doesn’t matter as you’re only adding one function, however if you were to add more functions to the action you would want to order the priorities in the order you want the functions to be called – with a lower number meaning earlier execution.

The final update is for the function used to process the output of the social sharing content. Here you now have a passed argument of the post ID and can use it in other functions to output content based on the current post.

function add_social_sharing( $post_id ) {
    $title = get_the_title( $post_id );
    $link = get_permalink( $post_id );

    // Output social media links
}

And there you have it, an example of how you can use some custom actions to easily enhance the content in your themes. By using actions here instead of putting everything in the template itself you can keep the templates a lot more maintainable and easier to read. It also allows you to write code once and apply it to many actions should you need to, for instance the social sharing code could be output on both actions before and after the content with the code only being written once.

Conclusion

WordPress hooks have been a key element in the success of WordPress. Through hooks developers have been able to create a plethora of useful plugins that interact with the WordPress core without breaking anything! Hopefully after reading this article you will understand a bit more the power of hooks and be able to put them to good use in your themes and plugins.