Did you know that actions and filters are the same things in WordPress? Because of that, you can filter the action and vice versa. Let me show you an example of this conflict.
WordPress has this concept of hooks. Actions are meant to just do an action on a particular event and filters are meant to pass a variable through a pipe. But in reality, add_action()
is just a wrapper for add_filter()
. You don’t believe me? Check the source code.
This means if we have the following code:
add_filter( 'example', '__return_false' );
$val = apply_filters( 'example', true ); // This is `false` now.
We can do this as well:
add_action( 'example', '__return_false' ); // add_action instead of add_filter.
$val = apply_filters( 'example', true ); // This is `false` now.
It will still work!
It doesn’t work the other way around
You can add a filter to action, but the problem is that do_action()
doesn’t return any value.
So you cannot do in any circumstance:
$val = do_action( 'example' ); // $val will always be `null`.
Thus you cannot:
add_filter( 'example', '__return_false' );
$val = do_action( 'example', true ); // `null`.
Action and filter with the same handle
This can be a problem in big plugins, especially if you don’t document the hooks.
If you have an action and filter with the same handle, this may lead to unexpected problems. Take a look at the following example:
add_action( 'send_something', function( $something ) {
// Something has been sent.
// Action is taken without any return statement.
} );
if ( apply_filters( 'send_something', true ) ) {
$something = function_should_send_something();
do_action( 'send_something', $something );
}
We have a filter that controls if something should be sent and an action when something has been sent. We want to hook into action but we accidentally hook into the filter as well. Causing it to be always null
. This is not expected to say the least! 😨
The opposite situation is not that harmful, you’ll only add another useless function call. See this:
add_filter( 'remove_something', function( $should_send ) {
return true;
} );
if ( apply_filters( 'remove_something', false ) ) {
$something = something();
function_should_remove_something( $something );
do_action( 'remove_something', $something );
}
The filter will work as expected, and action will call a function which only returns true.
I won’t show how giant mess would be created when you add action and filter and apply and do both of theme. And that’s just two dummy example hooks. Imagine having 200 hooks in the plugin and 5 of them overlapping 🤯
How to prevent this? Make sure the hook name for action and filter doesn’t overlap. This is the only way.