Adding an action within a function that is being called by add_filter

The answer when the question is about hooks is always either: timing, priority, or both.

Consider the following code:

add_action( 'shutdown', 'wpse_258451_shutdown' );
function wpse_258451_shutdown() {
  add_action( 'init', 'wpse_258451_init' );
}
function wpse_258451_init() {
  wp_die( 'I will never be called.' );
}

It should be obvious that the function wpse_258451_init() will never be called. This is because init is fired only once per page request and that is very near the beginning of the request. Further, shutdown is fired only once per page request and that is very near the end of the request.

What exactly happens in our code? WordPress gets to the first add_action() and adds a callback to the shutdown hook tag. WordPress fires off all sort of hooks before finally getting to the end of the request and firing shutdown. At priority 10, the default, WordPress will attempt to call the callback, which is the function wpse_258451_shutdown().

Inside the wpse_258451_shutdown() function, we add another action. This time to init with the callback of wpse_258451_init(). This gets added on to the global $wp_filter just fine. However, because we’re already past init and shutting down the request, this callback never fires.

How does this relate to your question?

If “I am being called” is being echoed but your action does not appear to be firing, then there are only two possible reasons.

  1. The hook has already fired and does not fire again on this request
  2. The hook isn’t fired at all on this request

How can I determine the timing of hooks

The following will echo every hook ( action and filter ) that is fired during a request.

add_filter( 'all', function( $a ) { 
  echo $a . "\\n";
  return $a; 
}, 10, 1 );

Another option would be to use Query Monitor by John Blackbourn.

Leave a Comment