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!
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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');
}
Method 2
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 );
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0