That’s a freaking bad practice I must say. Spent last two hours finding a solution to remove actions and filters added via Anonymous functions.
This is the code used on a Parent Theme, and I need to remove it.
/**
* Add custom columns to admin comments grid
* * Rate that user set.
*/
add_filter( 'manage_edit-comments_columns', function( $default ) {
$columns['smr_comment_rate'] = __( 'Rate', 'txtdmn' );
return array_slice( $default, 0, 3, true ) + $columns + array_slice( $default, 2, NULL, true );
});
Got toscho’s answer, played with it heavily, but no help. So, is there any other alternative that will remove actions/filters added via anonymous functions?
Thanks
The problem is that you can’t distinguish form an anonymous function and another, so yes, it is possible to remove a closure (i.e. anonymous function) but if more than one closure act on same filter at same priority you have to make a choice, remove them all, ore remove only one (without knowing exactly which).
I’ll show how to remove them all using a function highly derived from the one in the @toscho answer you posted:
I’ve renamed the function
remove_object_filter
because it can remove all types of object filters: static class methods, dynamic object methods and closures.The
$priority
argument is optional, but when removing closures it should be always used, otherwise the function will remove any closure added to the filter, no matter at which priority, because when$priority
is omitted, all the filters using the target class/method or closure are removed.How to use
Anonymous filters and actions can be removed natively using the following:
When generating the unique id using
spl_object_hash()
, anonymous functions are comparable to one another, so the full closure object doesn’t need to be re-created again.If multiple filters or actions are connected to the same tag with the same priority, then it’ll remove the latest filter or action which was added. If there’s one you need to keep, you would have to remove all the filters up to the one you need removed, then re-add the others as necessary.
This will generally come back to best practices. I’ll only ever use anonymous functions as part of a custom theme I’m developing for a client, where I don’t want the filter to be overwritten or removed. In any public theme or plugin I develop, I’ll use a factory to initialise a class, add all my filters and actions, then store the instance as a static variable.
EDIT
remove_filter
using an anonymous function doesn’t appear to be working with the latest versions of WordPress and PHP. The function_wp_filter_build_unique_id
has been updated since WordPress 5.3.0, and it removed some `spl_object_hash’ workarounds, which in turn prevent filters being removed in this manner.The only way I can now see to remove filters is by manually adjusting the
$wp_filter
global variable.What if you add your filter, with the priority 11, so it goes after? That’s ugly, but might work in your case.
Maybe someone need it: I modified a bit the code of
remove_object_filter
in @gmazzap answer, to make it works with WP 4.7+:I tested it a bit with an anonymous function and seems to work.
The code should be compatible also with WP version < 4.7 (but I didn’t test it).