WordPress Action Nesting: a cautionary tale

When you save a post in WordPress, the post’s data goes through wp_insert_post(), which in turn triggers the save_post action. So let’s say you have a callback hooking into save_post.

function my_first_callback( $post_id, $post ) {
  // do something...
}
add_action('save_post', 'my_first_callback', 10, 2);

So far, pretty simple. Now let’s put something in our callback function.

function my_first_callback( $post_id, $post ) {
  if ( $post->post_type == 'post' ) {
    wp_insert_post(array(
      'post_title' => 'A Post',
      'post_status' => 'publish',
      'post_type' => 'a_custom_post_type',
    ));
  }
}
add_action('save_post', 'my_first_callback', 10, 2);

Not a horribly complicated function. We’ll leave aside my reasons for creating a post in this callback (there’s a myriad of reasons why one might want to create or update a different post when a given post is saved) and focus on the consequences.

wp_insert_post(), called from my_first_callback() will once again trigger the save_post action, while we’re still in the middle of processing the first save_post action. So long as you avoid an infinite loop, there’s nothing necessarily wrong with that. But look closely inside do_action(), and you’ll find something else to worry about. Continue reading “WordPress Action Nesting: a cautionary tale”