Action Hooks in WordPress are the primary feature of the Plugin API. They enable plugin developers to “hook” into the WordPress stream and change how it capacities without modifying the middle code. By not altering core WordPress, users can upgrade to newer versions without losing any modifications to their plugins with the help of Action Hooks. Then in mind comes a question: what is Action Hooks in WordPress? Plugins would have no way to modify how WordPress works without Action hooks. In many ways, hooks represent what plugins are WordPress has two essential sorts of hooks: Action hooks; and Filter Hooks Action hooks allow you to execute a function (action) at a certain point in the WordPress flow. Let’s deep dive into Action Hooks in WordPress.
A Complete Guide to Action WordPress Hooks
Actions are PHP functions or class methods. What makes it action is the act of registering it to an action hook. In the previous section, you learned what action hooks are. However, without actions attached to them, the hooks don’t do anything alone. This is the point where plugins do something. When building plugins, you create custom actions that perform a specific task. Then, you attach that action to an action hook. WordPress provides the add_action() helper function for handling this.
<?php add_action( string $tag, callable $function_to_add, int $priority = 10, int $accepted_args = 1);
Parameters of Action Hooks In WordPress
This function accepts up to four parameters.
- $tag: Name of the action hook tag, which is the first parameter for “do_action()”.
- $function_to_add: A PHP callable, such as a function or class method, that executes when the action hook is fired.
- $priority: In what order the action should be fired? The default is 10, and negative numbers are allowed. Note that other plugins can set higher or lower priorities than your plugin’s actions.
- $accepted_args: The number of parameters to pass to your callback function. By default, only the first parameter will be passed to the function if the action has a parameter.
Action hooks can have multiple actions attached to them. Your plugin, other plugins, themes, and even WordPress can add actions to the same hook. For this reason, it’s important not to do anything that would interfere with other actions that may execute after yours. Now you should try creating your first action and attaching it to a hook. wp_footer is another common action hook executed on the front end. It’s fired just before the closing </body> tag in the HTML output.
Example Code for Action WordPress Hooks
With the following example code, you’ll create a basic plugin that outputs a message that says the site is powered by WordPress:
<?php /** * Plugin Name: Footer Message * Plugin URI: http://example.com/ * Description: Displays a powered by WordPress message in the footer. * Author: WROX * Author URI: https://www.wiley.com/en-us */ add_action( 'wp_footer', 'pdev_footer_message', PHP_INT_MAX ); function pdev_footer_message() { esc_html_e( 'This site is powered by WordPress.', 'pdev' ); }
Take a look at the add_action() call from the example plugin, shown here:
add_action( ‘wp_footer’, ‘pdev_footer_message’, PHP_INT_MAX )
The function call has three parameters passed into it. wp_footer is the action hook tag/name, which tells WordPress what action hook this action is attached to. Pdev_footer_message is the name of the function that should execute when the action hook is fired.
PHP_INT_MAX is the priority of the action.
It’s set to the maximum integer number possible, which tells WordPress that you want your action to execute after everything else (except actions with the same priority, which will execute in the order added).
How to Use Action Hook Functions in WordPress
When building plugins, you will almost exclusively use add_action() or do_action() for working with hooks. However, there are times when you’ll need to use one of the other functions WordPress provides for working with action hooks.
remove_action()
remove_action() is the third most useful function when working with action hooks. It allows you to remove an action that has been previously attached to a hook. At times, you may need to remove the actions that WordPress adds. You may also need to remove actions from other plugins, themes, or actions that you’ve added within your plugin. The function returns true if the action was successfully removed and false if the action isn’t registered or otherwise could not be removed.
<?php remove_action( string $tag, callable $function_to_remove, int $priority = 10 );
Parameters of remove_action()
This function accepts three parameters.
- $tag: The name of the hook that you want to remove the action from
- $function_to_remove: The name of the callable action to remove from the action hook
- $priority: The priority of the action to remove
Each of these parameters must match the parameters passed into the corresponding do_action() function call exactly. Otherwise, WordPress will not remove the action from the hook. Let’s take another look at the action from the previous section that added a custom message to the footer on the front end.
<?php add_action( 'wp_footer', 'pdev_footer_message', PHP_INT_MAX );
Now, look at the code required to remove that action.
<?php remove_action( 'wp_footer', 'pdev_footer_message', PHP_INT_MAX );
As you can see, the code is almost the same. The only difference is between the function names.
add_action() and remove_action()
If you remember this basic difference, you can remove actions with ease. You can remove any action added by WordPress, plugin, or theme from within your plugins. Most often, you’ll be removing actions that WordPress adds to change how it works in some way. Many of WordPress’ default actions are defined in the wp-includes/default-filters.php file. By browsing the code in this file, you’ll get a good understanding of how WordPress uses its action hooks out of the box.
remove_all_actions()
In rare cases, you may need to remove all actions for a given action hook or all actions with a specific priority on an action hook. More often than not, this may be something like testing or debugging the type of plugin. WordPress provides the remove_all_actions() function to handle this rather than running multiple remove_action() calls. This function always returns true when it has finished executing.
<?php remove_all_actions( string $tag, int|bool $priority = false );
The $tag parameter must be the name of the action hook to remove all actions from. You can set the $priority parameter to a specific number, which will remove only those actions that have that priority. Otherwise, the function will remove all actions, regardless of priority. Imagine that you wanted to stop all scripts, stylesheets, meta tags, or anything else from being output in the <head> area on the front end of the site.
You could do so by removing all actions from the wp_head hook.
<?php remove_all_actions( 'wp_head' );
Let’s say you wanted to remove all actions from that hook that had the priority of 1. By default, WordPress adds the following action with that priority. However, other plugins or the user’s theme may also add extra actions on this hook.
<?php add_action( 'wp_head', '_wp_render_title_tag', 1 );
To remove this action as well as all other actions with the same priority, you would use the following code:
<?php remove_all_actions( 'wp_head', 1 );
do_action_ref_array
The do_action_ref_array() function is nearly identical to the do_action() function. They both create an action hook. The difference is with how arguments are passed. Instead of passing multiple values as the second parameter and beyond, the function accepts an array of arguments. This array is passed along as parameters to any actions attached to the hook.
Now take a look at one of WordPress’s’ do_action_ref_array() calls. The following code snippet shows the core pre_get_posts hook, which is fired just before WordPress queries posts from the database on the front end of the site. It provides a point in the load for plugins to change how posts are loaded. The second parameter is an array with a single item. What this code is doing is passing along the instance of the WP_Query class ($this) for the given post query. This allows plugin authors to directly modify the query. Imagine that you wanted to build a simple plugin that randomly ordered the posts on the blog home page instead of the default ordering by post date. You would need to register a custom action on this hook and set the order.
<?php /** * Plugin Name: Random Posts * Plugin URI: http://example.com/ * Description: Randomly orders posts on the home/blog page. * Author: WROX * Author URI: https://www.wiley.com/en-us */ add_action( 'pre_get_posts', 'pdev_random_posts' ); function pdev_random_posts( $query ) { if ( $query-is_main_query() is_home() ) { $query->set( 'orderby', 'rand' ); } }
has_action
Sometimes you need to check whether a hook has any actions or whether a specific action has been added to a hook before executing code. The has_action() function is a conditional that returns true if an action is found or false if no action is found. Like remove_action() discussed earlier in this, the check will work only if the action has already been added before your check.
<?php has_action( string $tag, callable|bool $function_to_check = false );
Like most other action-related functions, the first parameter is the hook name that you want to check. The second parameter is optional and defaults to false. You can provide the callable if you want to check for a specific function or method attached to the hook. The return value for has_action() can be either a Boolean value or an integer, depending on the scenario. If the $function_to_check parameter is set to false, the function will return true if the hook has any actions, or false if it has none. However, if $function_to_check is set and the callback has been added to the hook, it will return an integer corresponding to the priority of the action. Otherwise, it will return false. Because an action’s priority can be 0, which evaluates to false, it’s important to use the identical comparison operator (===) rather than the equal comparison operator (==) in this scenario.
Example
In the next example, you will display a message based on whether any actions have been registered to the wp_footer action hook.
<?php if ( has_action( 'wp_footer' ) ) { echo 'Actions are registered for the footer.'; } else { echo 'No actions are registered for the footer.'; }
Try out an example where you check for a specific action attached to a hook. The following snippet will check if the wp_print_footer_scripts action is running on wp_footer. It also assigns the result of has_action() to the $priority variable.
Remember that the result can be false or an integer representing the action’s priority.
<?php $priority = has_action( 'wp_footer', 'wp_print_footer_scripts' ); if ( false !== $priority ) { printf( 'The wp_print_footer_scripts action has a priority of %d', absint( $priority ) ); }
did_action()
did_action() is another conditional function. The name may be confusing at first. You would think that it checks whether a specific action (function) has been executed. However, its purpose is to determine whether an action hook has already run.
<?php did_action( string $tag );
The function accepts a single parameter named $tag, which should be the tag name for the hook. It returns an integer corresponding to the number of times the action hook has fired (remember that action hooks can fire multiple times). Note that it doesn’t return a Boolean value if the hook hasn’t yet been executed. Instead, it returns 0, which evaluates to but is not identical to false. The first action hook available to plugins is plugins_loaded. Imagine that you wanted to check whether that hook has fired before setting a constant that your plugin is ready.
<?php if ( did_action( 'plugins_loaded' ) ) { define( 'PDEV_READY', true ); }
current_action
The current_action() function returns the name of the action hook that is currently being executed. It is generally useful if you need to use a single action on multiple action hooks but need the context of the hook to alter how something works. It can also be used in any scenario where you might not be sure what the action hook is, such as variable hooks. For example, assume you have a couple of actions for specific post types on the following core WordPress hook
<?php do_action( ;quot;save_post_{$post-;gt;post_type};quot;, $post_ID, $post, $update );
The previous hook name changes depending on the context. It could be save_post_post, save_post_page, or something else entirely. Study the following code that adds a single action to two different action hooks:
<?php add_action( 'save_post_post', 'pdev_check_hook_name' ); add_action( 'save_post_page', 'pdev_check_hook_name' ); function pdev_check_hook_name() { $action = current_action(); if ( 'save_post_post' === $action ) { // Do something. } elseif ( 'save_post_page' === $action ) { // Do something different. } }
As you can see, current_action() may return different results based on which action hook is currently running. The preceding code uses the return value of the function to set up a conditional statement.
register_activation_hook and register_deactivation_hook
WordPress provides functions for registering actions that will execute when a plugin is activated, deactivated, and even uninstalled. Technically, these functions allow you to create custom hooks and register a callback. However, you’ll learn some of the more common hooks you’ll use when building plugins in this section.
plugins_loaded
The most useful action hook for plugin developers is plugins_loaded. When WordPress loads all plugins, it is fired. It’s one of the earliest hooks that plugins can attach an action to and is ideal for running any setup code that your plugin might need. It fires before WordPress loads some of its constants and pluggable functions that plugins are allowed to override too. Many plugin authors use this hook to set constants or properties on their main plugin class. Let’s create a basic plugin that uses this hook and calls a setup class. To start with, you’ll have to make another folder for your plugin named plugin-bootstrap.
(plugin.php)
Then, add a file named plugin.php as the primary plugin file with the following code:
<?php /** * Plugin Name: Plugin Bootstrap * Plugin URI: http://example.com/ * Description: An example of bootstrapping a plugin. * Author: WROX * Author URI: https://www.wiley.com/en-us */ add_action( 'plugins_loaded', 'pdev_plugin_bootstrap' ); function pdev_plugin_bootstrap() { require_once plugin_dir_path( __FILE__ ) . 'Setup.php'; $setup = new \PDEV\Setup(); $setup->boot(); }
As you can see, the code adds an action to plugins_loaded. The action calls a setup class named Setup and calls its boot() method. You’ll also need to create a Setup.php file for the class with the following code:
<?php namespace PDEV; class Setup { public $path; public function boot() { // Store the plugin folder path. $this->path = plugin_dir_path( __FILE__ ); // Run other setup code here. } }
All this code does is store the plugin directory path when the boot() method is called. There are many things you can do here, depending on what your plugin needs to do. You don’t even need to use a class. There are dozens or hundreds of ways plugins set themselves up using the plugins_loaded hook. You’ll eventually figure out what best works for you.
Mastering the init_hook
for WordPress Customization
The init hook may be the most-used hook in WordPress. It is fired after most of WordPress is set up. Unlike plugins_loaded, themes also have access to this hook. WordPress adds a lot of internal functionality to the hook such as post type and taxonomy registration. This is generally the first hook that will make user data available. Essentially, if you need to run any code when most of the data and functions are available to you from WordPress, this is the earliest hook you should use. Imagine that you wanted to add excerpt support for pages in WordPress because the page post type doesn’t support this feature by default. You could use the following code to add the feature:
<?php add_action( 'init', 'pdev_page_excerpts' ); function pdev_page_excerpts() { add_post_type_support( 'page', [ 'excerpt' ] ); }
There are dozens of SEO plugins out there, but don’t let these discourage you from using the previous code to kick-start your competing product and gain a foothold on the market. You can create yourself, Action Hooks, in WordPress as per your needs. This article “Action Hooks in WordPress” is published for educational purposes. Apart from the Action Hooks In WordPress, we have other articles that you can study. You can consult these also for your learning.