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.
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.
Basically the “Plugin API,” which summons Filters and Hooks, consists out of the following functions:
apply_filters()
– execute
do_action
– execute
apply_filters_ref_array()
– execute
do_action_ref_array()
– execute
add_filter()
– add to stack
add_action()
– add to stack
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.
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']
)
);
}