Cómo evitar un bucle infinito en el callback save_post

7 may 2012, 13:21:14
Vistas: 16.2K
Votos: 22

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

Obtengo un bucle infinito al usar wp_update_post dentro de una función que se llama en save_post. Sé que es un problema común, pero no logro entender cómo evitarlo.

Quiero guardar el orden de mis posts (que son del tipo 'section'). He creado un meta box personalizado que contiene elementos HTML ordenables. En cada elemento hay un input oculto con name='sectionorder[]'. Así que cuando hago clic en el botón 'Actualizar' estándar de WordPress, se envía un array con todos los IDs de los posts (en orden) via POST. Este es el código donde recupero el array y quiero guardar el orden:

    // Actualizar el orden de las secciones
$sectionorder = $_POST['sectionorder'];
if (isset($sectionorder)) { // Evitar error si no hay secciones añadidas todavía
    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 inicia un bucle infinito. ¿Cómo lo evito? ¿Tal vez puedo hacerlo de una manera completamente diferente?

¡Aprecio tu ayuda!

0
Todas las respuestas a la pregunta 3
5
44

Puedes eliminar el callback del hook save_post, actualizar el post y luego volver a añadir el callback al hook. El Codex proporciona un ejemplo.

add_action('save_post', 'wpse51363_save_post');

function wpse51363_save_post($post_id) {

    //Verifica que no sea una rutina de auto guardado
     if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
          return;

    //Realiza comprobaciones de permisos! Por ejemplo:
    if ( !current_user_can('edit_post', $post_id) ) 
          return;

    //Verifica tu nonce!

    //Si llamas a wp_update_post, desengancha esta función para evitar un bucle infinito
    remove_action('save_post', 'wpse51363_save_post');

    // llama a wp_update_post para actualizar, lo cual llama a save_post nuevamente. Ej:
    wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));

    // vuelve a enganchar esta función
    add_action('save_post', 'wpse51363_save_post');
}
7 may 2012 13:43:21
Comentarios

¡Guau! Gracias por la rápida respuesta. Funciona de maravilla. No sé por qué no vi ese ejemplo de código yo mismo.

elgehelge elgehelge
7 may 2012 14:08:23

@Stephen, uso update_post_meta en una función enlazada a save_post, ¿debería también desenlazar y volver a enlazar después de update_post_meta?

Anagio Anagio
14 nov 2013 21:20:55

No, update_post_meta no activará (generalmente) save_post nuevamente.

Stephen Harris Stephen Harris
14 nov 2013 21:49:13

Después de perder una hora encontré esto y también me ahorró muchas más horas, gracias.

Manchumahara Manchumahara
22 dic 2019 07:39:16

funciona para mí, en el año 2020

gray gray
2 may 2020 02:00:38
3
19

No tengo suficiente reputación para comentar, así que estoy agregando una respuesta aunque la de Stephen es excelente y correcta. Simplemente no maneja los casos en los que deseas establecer la prioridad de la acción.

Si estableces la prioridad al agregar la acción pero no especificas la prioridad cuando la eliminas, seguirás obteniendo un bucle infinito.

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

// La forma INCORRECTA de manejar esto - conduce a un 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 );
20 jun 2014 21:05:37
Comentarios

¡Guau, gracias! Me estaba volviendo loco tratando de entender por qué seguía obteniendo el bucle infinito, incluso al agregar remove_action/add_action.

Banjer Banjer
25 ago 2014 03:27:25

WordPress Codex :: Referencia API de Plugins/Referencia de Acciones/save post :: Evitando bucles infinitos Ellos muestran esto. Si miras WordPress Codex :: Referencia de Funciones/remove action :: Uso "La prioridad de la función (tal como se definió cuando la función fue enganchada originalmente)." Si no se especifica, usa la prioridad por defecto (10). También conocido como - DEBES especificar la MISMA prioridad que cuando se agregó la acción, para REALMENTE eliminar la acción.

Michael Ecklund Michael Ecklund
2 dic 2016 18:50:11

Esta es la respuesta que estaba buscando. Gracias :)

José Manuel Blasco José Manuel Blasco
6 jun 2019 12:34:05
0

Este es un truco rápido y sucio, pero una forma es crear una variable global como $my_plugin_name_saving y simplemente establecerla en verdadero antes de llamar a wp_update_post y retornar si la variable ya está establecida.


<?php
/* Plugin Name: Mi nombre de plugin */

$my_plugin_name_saving = false;

function cc_publish_wpse_263985( $postid ) {
    global $my_plugin_name_saving;

    if ( ! empty( $my_plugin_name_saving ) ) {
        return;
    }

    $my_plugin_name_saving = true;
    wp_update_post(array('ID' => $postid, 'post_status' => 'private'));

}

add_action('save_post', 'cc_publish_wpse_263985');
14 sept 2022 02:33:54