2

I have a purchased theme that procedurally loads an action like this:

function func() {
    echo "head content";
}
add_action( 'wp_head', 'func', 5 );

Following the remove action codex I tried the following:

remove_action( 'wp_head', 'func', 5 );

Which did not work so I figured it was a priority issue so I adjusted both higher and lower neither worked. Then I tried wrapping the function in another function like:

function testfunc() {
    if (remove_action( 'wp_head', 'func', 5 )) {
        echo "removed action";
    }
}
add_action( 'wp_head', 'testfunc', 1000 );

Again playing with the priority. The whole time remove_action is returning true but not removing the action. Then I tried adding the wrapping function in the init action and it worked. Great! Unfortunately I have no idea why. Somewhat more perplexing is the wrapping function is required. Lastly, the codex specifically states:

It is also worth noting that you may need to prioritise the removal of the action to a hook that occurs after the action is added. You cannot successfully remove the action before it has been added.

And according to this codex entry both init and get_header (which worked) are before the wp_head action the function was hooked into. Can someone demystify this for me?

Edit: To answer @sumit's question the add_action happens via an include in the main themes functions.php (it includes library/core.php). The remove_action is in the functions.php of the child theme.

6
  • @toscho Why is wordpress.org not applicable?
    – JSP
    Apr 5, 2016 at 23:24
  • Because your question is not about that site.
    – fuxia
    Apr 6, 2016 at 1:44
  • Would you mind to explain that where did you add add_action and remove_action ?
    – Sumit
    Apr 6, 2016 at 7:56
  • @toscho I figured that was to distinguish between wordpress.com and the OSS version. Thanks for clarifying.
    – JSP
    Apr 6, 2016 at 10:43
  • 1
    For child themes and plugins (which loads before the parent theme), the action needs to be removed before it is added by the parent theme. If you need to remove core actions, you can remove it by using the same hook with the same priority. Apr 6, 2016 at 10:48

1 Answer 1

6

The issue here is that the child theme functions.php is loaded before the parent theme functions.php. Therefore, the ordering of the add/remove actions would be something like so:

//* From the child theme
remove_action( 'wp_head', 'func', 5 );
//* From the parent theme
add_action( 'wp_head', 'func', 5 );

The callback to func on the wp_head hook is removed before it's added. Therefore, it will appear that the child theme removing the action doesn't work. In reality, the remove_action() function is attempting to remove the func callback from the wp_head hook, but it hasn't been added yet.

The solution is to hook into WordPress anytime after the parent theme functions.php loads and then remove the action.

add_action( 'after_setup_theme', 'wpse_222809_after_setup_theme' );
function wpse_222809_after_setup_theme() {
  remove_action( 'wp_head', 'func', 5 );
}

This works because the after_setup_theme hook fires after the parent theme functions.php, so the ordering of the add/remove actions would thus be:

//* From the child theme
add_action( 'after_setup_theme', 'wpse_222809_after_setup_theme' );
//* From the parent theme
add_action( 'wp_head', 'func', 5 );
//* From the wpse_222809_after_setup_theme function hooked to after_setup_theme 
//*( hook added in child theme )
remove_action( 'wp_head', 'func', 5 );

This would also work with replacing after_setup_theme with init, as you figured out, because the init hook is fired after the parent theme functions.php and before wp_head.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.