What’s the Difference Between $wp_filter and $wp_actions

The global objects $wp_filter  and $wp_actions  hold details about the hooks that are registered and fire during the WordPress page load process.

If you’ve ever looked at any code that use the two objects, it can be difficult to work out how the objects differ and what data each of the objects hold.

In this article we’ll take a look at each object, list the differences between them and look at some code samples that illustrate how they work.

wp_filter

The $wp_filter object holds details of all of the filters and actions that are registered, here are some brief points describing what it does

  • Holds details of all actions and filters
  • Holds details of the functions linked to each action filter

Here is a code sample that illustrates what the $wp_filter object does

//declare a global to get access to the $wp_filter object
global $wp_filter;

//$wp_filter object contains all the actions and filters that have been added via the add_filter or add_action functions
//use the isset function to see if an action or filter has been added

//returns false - using var_export here as by default PHP echos nothing for false and 1 for true
echo '$wp_filter contains an entry for the "my_filter" tag - ' . var_export(isset($wp_filter['my_filter']),true) .'<br>';

//add a filter and function for the my_filter tag
add_filter( 'my_filter', 'hwn_simple_filter_function', 1 );

function hwn_simple_filter_function($value) {
return $value;
}

echo 'Called add_filter( "my_filter", "hwn_simple_filter_function", 1 )' . '<br>';

//returns true now we have added the entry via add_filter
echo '$wp_filter contains an entry for the "my_filter" tag - ' . var_export(isset($wp_filter['my_filter']),true) .'<br>';

//write out the data for the add_filter entry in $wp_filter
echo '<pre style="background:rgba(0,0,0,.1);">' . var_export($wp_filter['my_filter'], true) . '</pre>';

The output from the code above is shown below

the output of the wp_filter sample code

wp_actions

The $wp_actions  object only holds information about actions that have been fired during the page load, here is brief summary about what it does and does not do

  • Holds details of actions fired on the current page
  • Holds details of the number of times each action has been fired
  • Does not hold details of actions that have not been fired via the do_action function
  • Can hold details of actions that have been fired using do_action but have not been created using add_action

Here’s some code that illustrates how $wp_actions  can be used

//declare a global to get access to the $wp_actions object, we'll declare $wp_filter to compare and contrast
global $wp_actions, $wp_filter;

//$wp_filter object contains all the actions and filters that have been added via the add_filter or add_action functions
//$wp_actions object contains entries for all actions that have been fired with the do_action function
//use the isset function to see if an action or filter has been added

//returns false
echo '$wp_filter contains an entry for the "my_action" tag - ' .  var_export(isset($wp_filter['my_action']),true) .'<br>';

//add a filter and function for the my_action tag
function hwn_simple_action_function($value) {
}

add_action( 'my_action', 'hwn_simple_action_function', 1 );
echo 'Called  add_action( "my_action", "hwn_simple_action_function", 1 )' . '<br>';


//returns true now we have added the entry via add_action
echo '$wp_filter contains an entry for the "my_action" tag - ' .  var_export(isset($wp_filter['my_action']),true) .'<br>';

//although an entry has been added to $wp_filter when add_action was called
//there is still no entry in $wp_actions as we haven't invoked the action using the do_action function
echo '$wp_actions contains an entry for the "my_action" tag - ' .  var_export(isset($wp_actions['my_action']),true) .'<br>';

do_action("my_action");
echo 'Called  do_action("my_action")' . '<br>';

//now we have invoked the action using the do_action function then an entry is added to the $wp_actions object
echo '$wp_actions contains an entry for the "my_action" tag - ' .  var_export(isset($wp_actions['my_action']),true) . '<br>';

//note that if we call do_action on an action that we have not created an entry for in the $wp_filter object
//via the add_action function then the tag is still added to the $wp_actions object
do_action("action_not_yet_created_using_add_action");
echo 'Called  do_action("action_not_yet_created_using_add_action")'  . '<br>';
echo '$wp_actions contains an entry for the "action_not_yet_created_using_add_action" tag - ' .  var_export(isset($wp_actions['action_not_yet_created_using_add_action']),true) ."<br>";

//write out the data for the my_action entry in $wp_actions, will return the number of times the action has been fired
echo 'my_action has been fired ' .  $wp_actions['my_action'] . ' time(s).<br>';

//the $wp_actions['my_action'] value will increase as do_action is called multiple times
do_action("my_action");
echo 'Called  do_action("my_action")' . '<br>';
do_action("my_action");
echo 'Called  do_action("my_action")' . '<br>';
do_action("my_action");
echo 'Called  do_action("my_action")' . '<br>';

echo 'my_action has been fired ' .  $wp_actions['my_action'] . ' time(s).<br>';

//the did_action function also returns the number of times an action has been fired
echo 'my_action has been fired ' .  $wp_actions['my_action'] . ' time(s). The value of did_action("my_action") is - ' . did_action("my_action") . '<br>';

//write out the data for the my_action entry in $wp_filter, works the same as it would for a filter
echo '<pre style="background:rgba(0,0,0,.1);">' . var_export($wp_filter['my_action'], true) . '</pre><br>';

Here’s an image of the output of the script above

the output of the wp_actions sample code

There are a couple of questions I’ve seen regarding using  $wp_filter  and $wp_actions, I’ll answer those quickly before I wrap up this article

Is it Possible to Only List Actions that have been Registered?

You can get most of the way to doing this by listing the contents of the $wp_actions object but you have to bear in mind that only actions that have been fired via the do_action function will be present in the $wp_actions object.

So listing the contents of the $wp_actions object list actions that have been fired but will not list actions that have been registered using add_action but not fired using do_action.

I would guess that in most cases you’ll be able to get the information you need from $wp_actions but it’s worth bearing the limitation described above in mind.

Is it Possible to Find Out How Many Times a Filter Has Fired?

As far as I’m aware, there is no way to this.

It’s possible to do this for an action using either $wp_actions['<action name>'] or did_action('<action name>') but WordPress provides no functionality to count how many times a function has been fired.

I assume this is because you may want to know how many times an action has been fired to prevent functionality running too many times (there’s an excellent Stack Exchange thread about this here) but it’s unlikely that you ‘d need to prevent a filter running a certain number of times.

Is it Possible to tell if a Tag in $wp_filter Relates to an Action or a Filter?

The only way I’m aware that you can do this is to check if the tag is in the $wp_actions object, if it is then the tag is linked to action.

As mentioned in previous answers, there is a scenario when an action can have been registered with add_action but not fired using do_action so it won’t appear in the $wp_actions object.  In this scenario, I don’t think there is any way to distinguish an action set-up in  this way from a filter.

Final Thoughts

When I first started looking at the $wp_filter  and $wp_actions  objects I struggled to find certain information, so I hope this article has helped to explain the differences between the two objects and how they work.

If you have any further questions, or can provide better answers than I have to the questions above then please don’t hesitate to let me know in the comments.

This post is part of a series about debugging using the $wp_filter  and $wp_actions  objects, you can find the other posts listed below

Learn How To Change Your Store Without Hiring a Coder
Click here to enroll in our Free WooCommerce Coding Course

Further Reading

Here are the official docs for the functions mentioned in this article

Leave a Comment