WordPress 4.2 introduces a significant reworking of action and filter iteration to address bugs that arose from recursive callbacks and from callbacks that changed the hooked callbacks on currently running actions/filters.
What does this mean for you, the plugin or theme developer? In almost all cases, nothing. Everything should continue to run as expected, and this should fix a number of hard-to-trace bugs when different plugins are stepping on each others callbacks.
If your plugin directly accesses the $wp_filter
global rather than using the public hooks API, you might run into compatibility issues.
$wp_filter['save_post'][10]['my_special_key'] = array( 'function' => 'my_callback_function', 'accepted_args' => 2 );
This will no longer work, and will cause a fatal error. $wp_filter['save_post']
is no longer a simple array. Rather, it is an object that implements the ArrayAccess
interface.
You have two options to work around. The first (and preferred) method is to use the add_filter()
or add_action()
functions.
add_action( 'save_post', 'my_callback_function', 10, 2 );
If, for some reason, you absolutely cannot, you can still work around this.
if ( ! isset( $wp_filter[ 'save_post' ] ) ) {
$wp_filter[ 'save_post' ] = new WP_Hook();
}
$wp_filter[ 'save_post' ]->callbacks[ 10 ][ 'my_special_key' ] = array( 'function' => 'my_callback_function', 'accepted_args' => 2 );
unset( $wp_filter[ 'save_post' ][ 10 ][ $my_callback_id ] );
This will fail for the same reason as case one. To work around, you can use the standard remove_filter()
/ remove_action()
functions.
remove_action( 'save_post', 'my_callback_function', 10, 2 );
Or, if you absolutely must access the array directly:
if ( isset( $wp_filter[ 'save_post' ] ) ) {
unset( $wp_filter[ 'save_post' ]->callbacks[ 10 ][ $my_callback_id ] );
}
if ( isset( $wp_filter[ 'save_post' ] ) && is_array( $wp_filter[ 'save_post' ] ) ) {
// do something
}
This will always return false. $wp_filter[ 'save_post' ]
is a WP_Hook
object. To check if a hook has callbacks, use has_action()
or has_filter()
.
if ( has_action( 'save_post' ) ) {
// do something
}
If you're calling next() or prev() on the $wp_filter
array pointer to manually manage the order that callbacks are called in (or if you’re doing it to work around #17817), you will likely be unsuccessful. Use callback priorities, add_action()
/ add_filter()
, and remove_action()
/ remove_filter()
appropriately and let WordPress manage execution order.
Almost all other cases where you might manipulate the $wp_filter
global directly should continue to function as expected. The WP_Hook
object implements the ArrayAccess
and IteratorAggregate
interfaces so that, while it’s not recommended, you may continue to iterate over callbacks in $wp_filter
or directly retrieve priorities from the callback array.