Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have been using this site alot for solving my problems, but this time I did not succeed in finding and answer for my problem.

I get and infinite loop when using wp_update_post inside a function that is called on save_post. I know that this is a common issue, but I can't figure out how to avoid it.

I want to save the order of my posts (which is of the post-type 'section'). So I have made a custom meta box which contain some sortable html-elements. In each element there is an hidden input tag with name='sectionorder[]'. So when I click the standard WordPress 'Update' buttom, an array containing all the ID's of the posts (in order) are send via POST. So here is the code where I retrieve the array, and wants to save the order:

    // Update section sort order
$sectionorder = $_POST['sectionorder'];
if (isset($sectionorder)) { // Avoid error if there is no sections added yet
    foreach( $sectionorder as $no => $sectionID ) {
        $post_update = array();
        $post_update['ID'] = $sectionID;
        $post_update['menu_order'] = $no;
        wp_update_post( $post_update );
    }
}

But the problem is that it starts an infinite loop. How do I avoid that? Maybe I can do it in a completely different way?

Appriciate your help!

share|improve this question
add comment

2 Answers

up vote 7 down vote accepted

You can remove the callback from the save_post hook, update the post and then re-add the call back to the hook. The Codex gives an example.

add_action('save_post', 'wpse51363_save_post');

function wpse51363_save_post($post_id) {

    //Check it's not an auto save routine
     if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
          return;

    //Perform permission checks! For example:
    if ( !current_user_can('edit_post', $post_id) ) 
          return;

    //Check your nonce!

    //If calling wp_update_post, unhook this function so it doesn't loop infinitely
    remove_action('save_post', 'wpse51363_save_post');

    // call wp_update_post update, which calls save_post again. E.g:
    wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));

    // re-hook this function
    add_action('save_post', 'wpse51363_save_post');
}
share|improve this answer
    
Wow. Thanks for the quick reply. Works like a charm! Don't know why I didn't see that code example myself.. –  Helge May 7 '12 at 11:08
    
@Stephen, I use update_post_meta in a function hooked to save_post should I also unhook and rehook after update_post_meta? –  Anagio Nov 14 '13 at 19:20
    
No, update_post_meta won't (generally) cause save_post to be triggered. –  Stephen Harris Nov 14 '13 at 19:49
add comment

I haven't quite got the reputation to comment so I'm adding an answer even though Stephen's is excellent and correct. It just doesn't handle instances when you want to set the priority of the action.

If you set the priority when adding the action but don't specify priority when you remove it you will still get an infinite loop.

add_action('save_post', 'wpse51363_save_post', 25 );

// The WRONG way to handle this - leads to infinite loop

remove_action('save_post', 'wpse51363_save_post');
wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));
add_action('save_post', 'wpse51363_save_post');

// The RIGHT way to handle this - executes only once

remove_action('save_post', 'wpse51363_save_post', 25 );
wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));
add_action('save_post', 'wpse51363_save_post', 25 );
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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