Introducing WordPress Filter Hooks

It is important that we have control over the markup and content that WordPress is generating for us. Be it CSS classes, menus, page content, media, etc. 

And, WordPress Filter Hooks allow us to achieve just that. Filter hooks help us filter the data that WordPress is generating for us.

Technically, Filter hooks allow us to get and modify a piece of WordPress data before it is saved to the database or rendered to the browser. 

Just like Action Hooks allows us to add actions at the certain points of WordPress execution, Filter Hooks allows us to add filters to a piece of data at certain points of its execution.

That’s all. Nothing else. 

Just like Action Hooks, we can attach any number of filters to a particular filter hook with the help of add_filter() function. 

Just like Action Hooks, Filter hooks are understood better when you try them practically.

We already have a problem at hand. 

Using the capabilities of PHP, I want to detect the operating system of the user’s computer and add appropriate CSS class to the list of classes that body_class() function is generating.

But how we do that? 

Common, let’s view the source code of the body_class() function to figure out what we can do:

https://core.trac.wordpress.org/browser/tags/5.1.1/src/wp-includes/post-template.php#L576

It turns out that, the body_class() function is getting the final list of classes from the get_body_class() function and the source code of the get_body_class() function is right underneath it.

If you observe the source code of the get_body_class() function, you can see how WordPress is generating all those classes we have discussed in the previous lesson.

Basically, the get_body_class() function is creating an empty array called the $classes array and adding CSS classes to this array based on some dynamic function calls.

So, now, technically, the $classes array is a piece of WordPress data, Right? It contains all the dynamic classes that get outputted to the body tag. 

And the good thing about WordPress is, it helps us filter ( modify ) this $classes array by providing us a filter hook called body_class.

If you scroll down to the end of the get_body_class()function source code, we will find what we are looking for:

As you can see, just before returning the $classes array back to the body_class() function, get_body_class()function is triggering the body_class filter hook with the help of apply_filters() function, giving us a chance to add our own set of dynamic classes 

The apply_filters() function of filter hooks is similar to do_action() function of action hooks. 

While do_action() function triggers all the actions hooked into a particular action hook like wp_head, The apply_filters() function triggers all the filters hooked into a particular filter hook like body_class.

But, there is one important difference. 

Unlike actions that are linked to action hooks, Filters that are linked to a particular Filter Hook will receive the data as the argument so that we can modify the data and return it back.

You can see this in the above code. The apply_filters() function is sending the $classes array to the filters attached to the body_class filter hook.

Alright, enough talking. Let’s see this in action.

Go ahead and open up the functions.php file and put the following code in it:

/*----------------------------------------------------------*/
/* Adds new body classes
/*----------------------------------------------------------*/
add_filter('body_class', 'add_browser_classes');
function add_browser_classes( $classes ){
    // WordPress global variables with browser information
    global $is_gecko, $is_IE, $is_opera, $is_safari, $is_chrome;
 
    if( $is_chrome ) {
        $classes[] = 'chrome';
    }
    elseif( $is_gecko ){
        $classes[] = 'gecko';
    } 
    elseif( $is_opera ) {
        $classes[] = 'opera';
    }
    elseif( $is_safari ) {
        $classes[] = 'safari';
    }
    elseif( $is_IE ) {
        $classes[] = 'internet-explorer';
    }
    return $classes;
}

Nothing much going on in the above code.

We created a filter called add_browser_classes and attached it to the body_class filter hook.

The add_browser_classes filter receives the $classes array from the  apply_filters() function in the get_body_class() function.

And inside the add_browser_classes filter, first, we are gathering some browser-based global variables provided by WordPress.


// WordPress global variables with browser information
global $is_gecko, $is_IE, $is_opera, $is_safari, $is_chrome;

Then, we are using a bunch of IF conditions to check for a particular browser.

Next, we are checking for the chrome browser and if it is a chrome browser, we are adding the class “chrome” to the $classes array,

if( $is_chrome ) {
    $classes[] = 'chrome';
}

Next, we are doing the same for the remaining browsers.

Note: We are appending new classes to the array. We are not creating a new array by removing existing classes.

And Finally, we are returning back the updated $classes array.

return $classes;

Now, the body_class() function uses this updated $classes array to output the classes to the body tag.

So, we should see browser-based classes on the <body> tag. Let’s go back to the browser and view the page source of our Homepage.

Ah! There we go. It’s working. 

I visited the Homepage using the chrome browser and WordPress has added the class “chrome” to the body tag.

Get It?

We will be working with filter hooks all the time. Here is a full list of filter hooks available in WordPress:

https://codex.wordpress.org/Plugin_API/Filter_Reference

The most commonly used filter hooks are:

  • body_class
  • the_content
  • the_excerpt
  • excerpt_length

We will deal with the above filter hooks when we build our blog.

You do not always have to append the data, you override it

When working with filter hooks, no matter what filter hook it is, you will always receive some data in the form of a variable. 

It’s up to you whether to append new data to the or erase the existing data and put the new data. 

In the case of body_class filter hook, we appended more classes to the existing classes because we want to keep those dynamic classes from WordPress. 

But this is not always the case. Some times you just want to replace the existing data with yours. 

For example, if you want to remove all the classes added by WordPress and just keep your dynamic classes, you can do something like this:


add_filter('body_class', 'add_browser_classes');
function add_browser_classes(){
    return $my_custom_classes = array( 'my-own-css-class', 'i-dont-want-other-classes' );
}

In the above code, because we have decided to erase all the dynamic classes from WordPress, we are not interested in the $classes array, so we are not even using it inside our filter.

Instead, we built our own $my_custom_classes array with a couple of classes and returning it back. Now WordPress will output these couple of classes only.

Did you see that? We were successful in removing dynamic classes and just outputting the classes we need.

We still see the “customize-support” class because the filter related to this class is being executed after our add_browser_classes filter. If you want to remove this class too, you have to play around with the priorities.

Filters are prone to accidents, and they are dangerous

If you accidentally return an empty variable from your filter, we will end up not displaying data at all. 

In worst case scenarios, if a filter hook is saving changes to the database, we end up tampering or destroying the data altogether.

For example, in the below code snippet we are accidentally emptying the array just before returning it.

function add_browser_classes( $classes ){
    // WordPress global variables with browser information
    global $is_gecko, $is_IE, $is_opera, $is_safari, $is_chrome;
 
    if( $is_chrome ) {
        $classes[] = 'chrome';
    }
    return $classes = array();
}

In the above case, We ended up removing all the body classes. Even the body classes that we and WordPress added. 

This could break the site because we could be writing CSS and JS dependent on the body classes.

So, always make sure you return data correctly.

Always remember to return the data from your filter

The whole point of a filter is to modify a piece of data according to our requirement and return it.

If you forget to return the data, WordPress will throw a warning like this:

If debugging is turned off, you’ll never find this warning, and you’ll be banging your head figuring out the reason behind the code failure or why the site broke!

So, be careful!

If you understood the concept of filters and filter hooks, feel free to skip the next lesson. 

In the next lesson, we will take a look at the execution flow of WordPress filter hooks.