Cómo evitar el bucle infinito en la devolución de llamada save_post

12

He estado usando mucho este sitio para resolver mis problemas, pero esta vez no logré encontrar y responder a mi problema.

Obtengo un bucle infinito cuando uso wp_update_postdentro de una función que se llama save_post. Sé que este es un problema común, pero no puedo entender cómo evitarlo.

Quiero guardar el orden de mis publicaciones (que es de la 'sección' de tipo de publicación). Así que hice un meta cuadro personalizado que contiene algunos elementos html ordenables. En cada elemento hay una etiqueta de entrada oculta con nombre = 'sectionorder []'. Entonces, cuando hago clic en el botón estándar 'Actualizar' de WordPress, se envía una matriz que contiene todos los ID de las publicaciones (en orden) a través de POST. Entonces, aquí está el código donde recupero la matriz y quiero guardar el pedido:

    // 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 );
    }
}

Pero el problema es que comienza un ciclo infinito. ¿Cómo evito eso? ¿Tal vez puedo hacerlo de una manera completamente diferente?

¡Agradece tu ayuda!

elgehelge
fuente

Respuestas:

26

Puede eliminar la devolución de llamada del save_postenlace, actualizar la publicación y luego volver a agregar la llamada al enlace. El Codex da un ejemplo .

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');
}
Stephen Harris
fuente
Guau. Gracias por la rápida respuesta. ¡Funciona de maravilla! No sé por qué no he visto que a mí mismo ejemplo de código ..
elgehelge
@Stephen, lo uso update_post_metaen una función conectada a save_post¿También debería desenganchar y volver a conectar update_post_meta?
Anagio
No, update_post_metano causará (generalmente) save_postque se active.
Stephen Harris
Después de perder una hora encontré esto y esto también ahorró más horas, gracias.
Manchumahara
13

Todavía no tengo la reputación de comentar, así que agrego una respuesta a pesar de que Stephen es excelente y correcta. Simplemente no maneja las instancias cuando desea establecer la prioridad de la acción.

Si establece la prioridad al agregar la acción pero no especifica la prioridad cuando la elimina, obtendrá un bucle infinito.

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

// La forma INCORRECTA de manejar esto: conduce al bucle infinito

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

// La forma CORRECTA de manejar esto: se ejecuta solo una vez

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 );
Charles Jaimet
fuente
1
¡Wow gracias! Me estaba volviendo loco tratando de descubrir por qué todavía obtenía el bucle infinito, incluso cuando agregaba remove_action/add_action.
Banjer
1
WordPress Codex :: Complemento API / Referencia de acción / guardar publicación :: Evitar bucles infinitos Lo demuestran. Si observa WordPress Codex :: Referencia de función / acción de eliminación :: Uso "La prioridad de la función (como se definió cuando la función se enganchó originalmente)". Si no se especifica, utiliza la prioridad predeterminada (10). A / K / A: debe especificar la MISMA prioridad que cuando se agregó la acción, para eliminar REALMENTE la acción.
Michael Ecklund
Esta es la respuesta que estaba buscando. Gracias :)
manuman94