Articles, Tutorials


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

add_filter on a typical request

Figure 1: add_filter on a typical request

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)

Around the web

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s