How do filters and hooks really work in PHP

How does filters and hooks actually work in WordPress?

I’m asking about something advanced. How is it implemented in PHP? E.g how does it collect all the hooks from the different plugins and “attach” them to the core hooks etc.

Related posts

2 comments

  1. Overview

    Basically the “Plugin API,” which summons Filters and Hooks, consists out of the following functions:

    1. apply_filters()execute
    2. do_actionexecute
    3. apply_filters_ref_array()execute
    4. do_action_ref_array()execute
    5. add_filter()add to stack
    6. add_action()add to stack

    Basic Internals

    Overall there’re a couple of globals (what else in WordPress world) involved:

    global $wp_filter, $wp_actions, $wp_current_filter, $merged_filters;
    

    The first one $wp_filter is a global Array that holds all filter names as subarrays. Each of those subarrays then holds even more subarrays that are callbacks summoned under a priority array.

    Brief in-depth

    So when an execute function is called, WordPress searches those globals arrays for the keys with that name. Then the attached callbacks get executed priority after priority. The only thing that happens up front are callbacks attached to the all filter.

    When you add a callback using add_action or add_filter, then WordPress first calculates a “unique” ID to not overwrite already attached callbacks.

    $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
    

    Then it adds your callback to the global $wp_filter stack:

    $wp_filter[ $tag ][ $priority ][ $idx ] = array(
        'function'      => $function_to_add,
        'accepted_args' => $accepted_args
    );
    

    As you can see the main sub array is the $tag (or action/filter name), then everything is summoned under a specific priority, and then the “unique” callback/ID string gets used as key.

    Later, when a filter gets called – happening with the $tag/action-/filter-name – the array gets searched and the callbacks get called. As it is using call_user_func_array it doesn’t really matter how many arguments are attached. WordPress resolves that by itself.

    foreach ( (array) current( $wp_filter[ $tag ] ) as $the_ )
    {
        call_user_func_array(
            $the_['function'], 
            array_slice(
                $args, 
                0, 
                (int) $the_['accepted_args']
            )
        );
    }
    
  2. Hooks are included in both the WordPress core files and some parent themes files. They enable you to hook in content in a specific location in the file.

    An example is the wp_head hook in WordPress. You can use this hook in your child theme to add content in that location’

    Example:

    add_action('wp_head', 'add_content_to_head');
    function add_content_to_head() {
    echo 'Your Content';
    }
    

    Some premium themes also include action hooks which you can use in a child theme to do the same thing. Here’s a visual map which includes all the the action hooks and the position they output your content in the Genesis theme framework.

    Example:

    add_action('genesis_header', 'add_content_to_header');
    function add_content_to_header() {
    echo 'Your Content';
    }
    

    Here’s what the hook looks like if you opened the header.php file in the Genesis theme framework:

    do_action( 'genesis_header' );
    

    Here’s a list of WordPress hooks you can use in many ways.

    Filters enable you to modify the output of an existing function and is included in both the WordPress core files and some parent theme frameworks like Genesis.

    Here’s a list of the filters you can use with the Genesis Design Framework

    Here’s a list of the filters included in WordPress

    Here’s an example of how you can use a filter in a theme framework like Genesis:

    add_filter( 'comment_author_says_text', 'custom_comment_author_says_text' );
    function custom_comment_author_says_text() {
    return 'author says';
    }
    

    The above code can be used in a child theme to modify the author says text in your comments. It works in any theme.

    Here’s another example which customizes the length of excerpts to 50 words:

    add_filter( 'excerpt_length', 'change_excerpt_length' );
    function change_excerpt_length($length) {
    return 50; 
    }
    

    You’ll find the the_excerpt() function in the wp-includes/post-template.php file.

    Here’s what it looks like:

      function the_excerpt() {
            echo apply_filters('the_excerpt', get_the_excerpt());
    }
    

    You can also use hooks and filters in plugins to do exactly the same thing and the code won’t be lost when you update the parent theme or WordPress.

    Basically, hooks and filters enable you to customize and modify both WordPress and your parent theme without editing the core WordPress files or your parent theme files.

    Its significantly easier to customize a child theme when the parent theme framework includes hooks and filters because you never need to edit the parent themes template files. This way you can safely change themes as well.

Comments are closed.