Global function add_filter
is an integral part of WordPress core. Together with the function apply_filters
, you can extend WordPress core, plugins and themes without touching a single line in them. Thanks to this, updates become straightforward — just copy and replace the old code with the new one.
I’ll be explaining sections of WordPress core, line by line, in a series of articles, starting with this one. These topics will be of technical character. If you want to read about how to use this and that, I’ll include links to other resources at the end of each article.
Quick facts (WordPress v4.1)
- location: wp-includes/plugin.php
- global function available in plugins, themes
- loaded in
SHORTINIT
mode too - since: 0.7.1 (<= 2004)
- access: public
add_filter function
function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) { global $wp_filter, $merged_filters; $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority); $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args); unset( $merged_filters[ $tag ] ); return true; }
On the second line, global variables $wp_filter
and $merged_filters
are made available to the function by using the global
keyword. Both of them are initialized as an array type at the top of the same file.
$wp_filter
is a multidimensional associative array storing all added filter hooks to a $tag
by a $priority
and a special $idx
returned from the function _wp_filter_build_unique_id
. That function basically checks if a $function_to_add
is a string (e.g. add_filter( 'init', 'my_custom_function' )
), an object (e.g. add_filter( 'init', $this )
or any other type:
function _wp_filter_build_unique_id($tag, $function, $priority) { global $wp_filter; static $filter_id_count = 0; if ( is_string($function) ) return $function; if ( is_object($function) ) { // Closures are currently implemented as objects $function = array( $function, '' ); } else { $function = (array) $function; } // function continues ...
On the 5th line, we can see that if it’s a string, the $idx
will be that string (callback’s function name), nothing fancy. If it’s an object (line 8), we need to convert it into an array of ( <object instance>, '' )
type. The reason behind this is that function for executing custom functions (call_user_func) requires that format.
Going back to the add_filter
function, the $function_to_add
callback is finally stored with the number of accepted arguments for that callback in an array in the 3rd dimension of the $wp_filter
array. Therefore, a $wp_filter
looks like

during a typical request.
Finally, true
is returned. Honestly, I don’t know why; maybe for a historical purpose (e.g. plugins, themes or even Core might have relied on this behavior and WordPress developers didn’t want to break the compatibility with them)