Removing Hooks in WordPress (Actions or Filters)
To remove a hook, you need to modify the source code and delete the hook call, which is usually impossible because the hooks are located in the core or in a plugin. Here we will talk about how to remove callback functions attached to a hook.
To remove a function attached to a filter/action, one of the following functions is used:
For reference. These are completely identical functions and both of them remove the hook, whether it is a filter or an action, in this case, it doesn't matter. For example, we can remove both actions and filters using only the remove_filter() function or only the remove_action() function. However, for code clarity, it is still better to remove filters using remove_filter() and actions using remove_action().
To remove a hook, you need to know:
- The hook name, for example,
wp_footer
. - The name of the attached function, for example,
my_action_function
. -
The execution priority of the hook, if it was set when the hook was created. If the priority was not set when the hook was created, it is equal to 10 and is not required to be specified when removing it.
If you need to remove a hook with a priority other than 10 and you did not specify it, the hook will NOT be removed!
Example of Removing a Hook
Suppose somewhere in a plugin, the function my_action_function
is attached to the wp_footer
action, which outputs text in the theme footer:
add_action( 'wp_footer', 'my_action_function' ); function my_action_function( $text ){ echo 'This is the text in the footer!'; }
In the theme, we need to remove this action so that the text in the footer is not displayed. To do this, you can add the following code to the theme's functions.php file:
remove_action( 'wp_footer', 'my_action_function' );
Important: The hook should be removed after it is added, but has not yet been executed.
Another Example of Removing a Hook
Demonstration of adding and removing a hook:
// add a function to the my_action action add_action( 'my_action', 'my_action_function' ); function my_action_function( $text ){ echo 'Hello!'; } // create the action do_action( 'my_action' ); //> Hello! // remove the previously added action remove_action( 'my_action', 'my_action_function' ); // create the action again do_action( 'my_action' ); // will not output anything...
Removing with consideration of priority
The priority must match the one that was set when the hook was added.
// if added like this add_filter( 'my_filter', 'function_name', 99 ); // then it should be removed like this remove_filter( 'my_filter', 'function_name', 99 );
Removing a hook of a static method of a class
// added like this add_filter( 'my_filter', [ 'My_Class', 'static_method_name' ], 15 ); // it should be removed like this remove_filter( 'my_filter', [ 'My_Class', 'static_method_name' ], 15 );
Removing a hook of a non-static method of a class (if there is access to $this - an instance of the class)
class A { function __construct(){ add_action( 'my_action', [ $this, 'method_name' ], 15 ); } function method_name(){ echo 'Hello!'; } } $class = new A(); // instance // to remove, you need to find the variable in which the // class instance was saved when created, in this case it's $class remove_action( 'my_action', [ $class, 'method_name' ], 15 );
Removing a hook of a non-static method of a class (if there is NO access to $this - an instance of the class)
It is impossible to remove a hook for an object of a class to which you do not have access using standard WP functions. However, you can do this using the following custom functions:
GitHub<?php /** * Remove Class Action Without Access to Class Object * * @see remove_object_filter() */ function remove_object_action( string $hook_name, $static_callback, $priority = null ): bool { return remove_object_filter( $hook_name, $static_callback, $priority ); } /** * Remove filters without access to class object (instance). * * To use remove_filter() function you need to have access to class instance, * or the filter should be added using static method as hook callback. * This function allows you to remove filters with callbacks you don't have access to. * * @param string $hook_name Filter name to remove. * @param string|array $static_callback Hook callback where instance represented as class name. * Eg: [ '\Space\My_Class', 'my_method' ] OR '\Space\My_Class' to remove all methods added to hook. * @param int|null $priority (optional) Priority of the filter. If not set all hooks with any priority will be removed. * * @return bool Whether the hook is removed. * * @requires WP 4.7+ * @author Kama (wp-kama.com) * @version 2.0 */ function remove_object_filter( string $hook_name, $static_callback, $priority = null ): bool { if( is_string( $static_callback ) ){ // '\Space\My_Class::my_method' or '\Space\My_Class' $static_callback = explode( '::', $static_callback ) + [ '', '' ]; } $found = _find_hook_callback_instances( $hook_name, $static_callback, $priority ); $res = 0; foreach( $found as $item ){ $callback = [ $item['instance'], $item['method'] ]; $res += (int) remove_filter( $hook_name, $callback, $item['priority'] ); } return (bool) $res; } /** * Finds the instance of the object whose specified method is added for the specified hook. * * To use remove_filter() function you need to have access to class instance, * or the filter should be added using static method as hook callback. * This function allows you to find class instance that was used when the hook was added. * * @param string $hook_name Filter name. * @param string|array $static_callback Hook callback where instance represented as class name. * Eg: [ '\Space\My_Class', 'my_method' ] * or [ '\Space\My_Class' ] to get all methods added for the hook. * @param int|null $priority (optional) Priority of the filter. * * @return array{ instance: object|string, method:string, priority:int }[] * * @author Kama (wp-kama.com) * @version 1.1 */ function _find_hook_callback_instances( string $hook_name, array $static_callback, $priority = null ): array { global $wp_filter; /** @var \WP_Hook $wp_hook WP hooks. */ $wp_hook = $wp_filter[ $hook_name ] ?? null; if( empty( $wp_hook->callbacks ) ){ return []; } $find_class_name = ltrim( $static_callback[0], '\\' ); //> \Space\My_Class >>> Space\My_Class $find_method_name = $static_callback[1] ?? ''; $found = []; foreach( $wp_hook->callbacks as $the_priority => $hooks_data ){ foreach( $hooks_data as $hook_data ){ $real_callback = $hook_data['function'] ?? null; if( ! is_array( $real_callback ) ){ continue; } [ $object, $the_method_name ] = $real_callback; $class_name = is_object( $object ) ? get_class( $object ) : $object; if( $class_name !== $find_class_name || ( $find_method_name && $the_method_name !== $find_method_name ) || ( null !== $priority && $the_priority !== $priority ) ){ continue; } $found[] = [ 'instance' => $object, 'method' => $the_method_name, 'priority' => $the_priority, ]; } } return $found; }
Usage example.
Suppose we have the following class:
namespace My\Space; class MyClass { public function __construct() { add_action( 'some_action_hook', [ $this, 'my_method' ], 11 ); add_filter( 'some_filter_hook', [ $this, 'my_method' ], 11 ); } public function my_method() { die( 'my_method triggered: '. current_filter() ); } }
We initialized the class, as a result of which 2 hooks were added:
new \My\Space\MyClass();
Now, it will be impossible to remove the hooks of this class using standard WP functions because to remove a hook, we need to have access to a specific instance of the class, which we do not have. However, thanks to the above functions, we can do this simply by specifying the class name, method, and priority.
Let's consider all the options for calling the function to remove the hook:
remove_object_action( 'some_action_hook', [ 'My\Space\MyClass', 'my_method' ], 11 ); remove_object_action( 'some_action_hook', [ '\My\Space\MyClass', 'my_method' ], 11 ); remove_object_action( 'some_action_hook', [ '\\My\\Space\\MyClass', 'my_method' ], 11 ); remove_object_action( 'some_action_hook', [ \My\Space\MyClass::class, 'my_method' ], 11 ); remove_object_action( 'some_action_hook', '\My\Space\MyClass::my_method', 11 ); remove_object_action( 'some_action_hook', 'My\Space\MyClass::my_method', 11 ); // or similarly for filters remove_object_filter( 'some_filter_hook', [ 'My\Space\MyClass', 'my_method' ], 11 ); // etc...
Or if we need remove all hooks no metter what prioritet is, we may skip $priority parameter:
remove_object_action( 'some_action_hook', [ 'My\Space\MyClass', 'my_method' ] );
Removing a hook added by an anonymous function (closure)
It is not so easy to remove a hook with a closure. For example, the following code will not work:
add_action( 'my_action', function(){ echo 'Hello!'; } ); remove_action( 'my_action', function(){ echo 'Hello!'; } ); // does not work!
To reliably remove a hook using a closure, you can only do it if the closure was created in a variable and we have access to that variable:
$my_func = function(){ echo 'Hello!'; }; add_action( 'my_action', $my_func ); remove_action( 'my_action', $my_func ); // It works!
A less reliable, but still a way to remove a hook with a closure when we do not have access to the closure:
/** * Removes the hook when it has been added by a closure. * The accuracy of the function is not guaranteed - the first hook * that matches the priority and the number of hook arguments will be removed. * * @param string $name * @param int $priority * @param int $accepted_args */ function remove_closure_hook( $name, $priority = 10, $accepted_args = 1 ): bool { global $wp_filter; if( empty( $wp_filter[ $name ]->callbacks[ $priority ] ) ){ return false; } $callbacks = & $wp_filter[ $name ]->callbacks[ $priority ]; // Find our hook. // It is not always possible to identify it unambiguously, but // at least we know that it was created with a closure // and we know it's priority and number of parameters. foreach( $callbacks as $key => $hook ){ if( ! ( $hook['function'] instanceof Closure ) ){ continue; } if( $hook['accepted_args'] !== $accepted_args ){ continue; } // remove unset( $callbacks[ $key ] ); // first suitable only return true; } return false; }
Usage example:
add_action( 'my_action', function(){ echo 'Hello!'; } ); do_action( 'my_action' ); // Hello! remove_closure_hook( 'my_action', 10, 1 ); do_action( 'my_action' ); // (empty)
—