WordPress Hooks – The Difference Between Actions and Filters
WordPress handles most of what’s needed to output your content to the user’s screen with PHP and SQL, producing that information in HTML with the capability to manipulate it further with JavaScript. However, there may be times when you want to modify how WordPress works with that data on the back end or how it’s displayed to the user. There are a few reasons for this, including ensuring ADA compatibility, modifying content before it’s saved, or simply deferring enqueued JavaScript files. In circumstances where you need to alter the data, either to change it before output or to add an additional function while something is loading, WordPress offers hooks in two flavors: Actions and FIlters.
So, what is a WordPress hook? It is an additional function that you can use in order to interrupt WordPress’s normal operations and run some of your own. This can be very handy because WordPress does not always do exactly what we want every time with every piece of content. For instance, WordPress does not currently have a way to identify if an enqueued JavaScript file should be marked as deferred. You want to defer some of those files to prevent render blocking on the page and speed up your site on the whole. You don’t want to defer every file because some of the JavaScript you’ve written could depend on those other files and will break unless they’re loaded properly. Because you need to be selective with this, you can use one of the available hooks in order to specify which files should be enqueued.
Filters and actions are the two available hooks that you can use with WordPress. Although they’re very similar, there are key distinctions that differentiate them. For the above example – ensuring that enqueued JavaScript files are enqueued – you would want to use a filter in order to achieve this. WordPress’s normal procedure is to take an enqueued file (usually set in your theme’s functions.php file) and insert each of these files in the head or at the end of your document with the appropriate HTML to let the browser know how to render it.
We’re not going to muddle up this article with examples of enqueueing JavaScript files, but if you need direction on that, you can view my article here.
1 2 3 4 5 6 7 8 9 10 | function defer_js_files( $url ){ if ( TRUE == strpos( $url, 'jquery.js' ) || //If this is a jQuery file TRUE == strpos($url, 'jquery.min.js' ) || //If this is a minified jQuery file is_admin() //If this is the WordPress Dashboard ) { return $url; //Return the URL without modifying it } return str_replace( ' src', ' defer src', $url); } add_filter( 'script_loader_tag', 'defer_js_files', 10); |
The above example, when placed in your theme’s functions.php file, uses WordPress’s filter hook in order to add a ‘defer’ to script files that aren’t jQuery and are not on the admin dashboard. This can be very helpful when trying to speed up your site and eliminating render-blocking assets. This hook accepts input from WordPress and modifies it before returning it back to WordPress to then be output on the browser or saved in the database. This is the main purpose of the filter hook: to modify a portion of the content and return it to WordPress before it’s given to the user’s browser.
The action hook exists in a bit of a different place. It will hook into WordPress’s normal operations and accept a portion of the information that the system is working with, but it can not modify the information that WordPress has and does not return it to WordPress to be output or saved. What this would be used for may be more back-end development, such as triggering an additional function when an editor saves a page.
Let’s write a fairly annoying piece of code that will send the site’s owner an email whenever a new post has been published on the site. The following code would be placed in the functions.php file.
1 2 3 4 5 6 7 8 9 10 11 12 | function run_an_additional_function( $post_id, $post, $update ) { if ( 'post' != $post->post_type ) { return; //Only runs on saving something that has 'post' Post Type } if ($update){ return; //Only runs when a new post is created, not an update } wp_mail( get_bloginfo('admin_email'), 'A New Post Has Been Added!', '<p>A new post has been added to your site! ' . get_the_title($post_id) . ' was added today!<br />' . 'Check it out <a href="' . get_the_permalink($post_id) . ' target="_blank">here</a>!</p>'); } add_action( 'save_post', 'run_an_additional_function', 10, 3 ); |
The most important part of this code is the add_action() line at the end. This tells WordPress that when a post is saved, it should run the function run_an_additional_function(). It passes its three arguments to it: the Post ID, the Post Object, and whether or not this save is an update to an existing page or post. In our code, we’re first checking to see if what’s being saved has the Post Type ‘post’. If it does, then it moves onto the check to see if this save is an update. If this is also a newly published post, then this function moves to sending an email informing the site owner – who most likely is already fully aware – an email letting them know all about the post.
As you can see, our action hook does not change the information that’s being saved. It has the capability to use the information to perform additional *actions* with it, but can’t modify – or *filter* – what’s being saved to the database. That would be the main difference between actions and filters, however similar the actions may be.
These hooks are important to WordPress programming simply to make the entire flow of information more manageable for the developers. There are a lot of needs to work with information in certain ways or add an alert when a new post has been saved, that wouldn’t be available without these hooks. That’s why it’s important to ensure that your coding also provides users with actions and filters that they’re able to work with when you provide them