Come evitare un loop infinito nel callback save_post in WordPress

7 mag 2012, 13:21:14
Visualizzazioni: 16.2K
Voti: 22

Ho utilizzato molto questo sito per risolvere i miei problemi, ma questa volta non sono riuscito a trovare una risposta alla mia domanda.

Ottengo un loop infinito quando uso wp_update_post all'interno di una funzione richiamata da save_post. So che è un problema comune, ma non riesco a capire come evitarlo.

Voglio salvare l'ordine dei miei post (che sono di post-type 'section'). Quindi ho creato un meta box personalizzato che contiene elementi html ordinabili. In ogni elemento c'è un tag input nascosto con name='sectionorder[]'. Quando clicco sul pulsante standard 'Aggiorna' di WordPress, un array contenente tutti gli ID dei post (in ordine) viene inviato via POST. Ecco il codice con cui recupero l'array e voglio salvare l'ordine:

    // Aggiorna l'ordinamento delle sezioni
$sectionorder = $_POST['sectionorder'];
if (isset($sectionorder)) { // Evita errori se non ci sono ancora sezioni
    foreach( $sectionorder as $no => $sectionID ) {
        $post_update = array();
        $post_update['ID'] = $sectionID;
        $post_update['menu_order'] = $no;
        wp_update_post( $post_update );
    }
}

Ma il problema è che si crea un loop infinito. Come posso evitarlo? Forse posso farlo in un modo completamente diverso?

Apprezzo il vostro aiuto!

0
Tutte le risposte alla domanda 3
5
44

Puoi rimuovere il callback dall'hook save_post, aggiornare il post e poi riaggiungere il callback all'hook. La Codex fornisce un esempio.

add_action('save_post', 'wpse51363_save_post');

function wpse51363_save_post($post_id) {

    //Verifica che non sia una routine di salvataggio automatico
     if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
          return;

    //Esegui controlli di permesso! Ad esempio:
    if ( !current_user_can('edit_post', $post_id) ) 
          return;

    //Verifica il tuo nonce!

    //Se chiami wp_update_post, scollega questa funzione per evitare un loop infinito
    remove_action('save_post', 'wpse51363_save_post');

    // chiama wp_update_post per l'aggiornamento, che richiamerà save_post. Esempio:
    wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));

    // riaggancia questa funzione
    add_action('save_post', 'wpse51363_save_post');
}
7 mag 2012 13:43:21
Commenti

Wow. Grazie per la rapida risposta. Funziona perfettamente! Non so perché non ho visto io stesso quell'esempio di codice..

elgehelge elgehelge
7 mag 2012 14:08:23

@Stephen, io uso update_post_meta in una funzione agganciata a save_post, dovrei anche scollegare e riagganciare dopo update_post_meta?

Anagio Anagio
14 nov 2013 21:20:55

No, update_post_meta generalmente non causa il trigger di save_post.

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

Dopo aver perso un'ora ho trovato questo e mi ha fatto risparmiare ancora più tempo, grazie.

Manchumahara Manchumahara
22 dic 2019 07:39:16

funziona per me, nell'anno 2020

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

Non ho ancora abbastanza reputazione per commentare quindi aggiungo una risposta anche se quella di Stephen è eccellente e corretta. Semplicemente non gestisce i casi in cui vuoi impostare la priorità dell'azione.

Se imposti la priorità quando aggiungi l'azione ma non specifichi la priorità quando la rimuovi, otterrai comunque un loop infinito.

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

// Il modo SBAGLIATO di gestire questo caso - porta a un loop 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');

// Il modo GIUSTO di gestire questo caso - viene eseguito solo una volta

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 giu 2014 21:05:37
Commenti

Wow grazie! Stavo impazzendo cercando di capire perché continuavo ad avere il loop infinito, anche aggiungendo remove_action/add_action.

Banjer Banjer
25 ago 2014 03:27:25

WordPress Codex :: Plugin API/Action Reference/save post :: Evitare loop infiniti Lo dimostrano. Se guardi WordPress Codex :: Function Reference/remove action :: Utilizzo "La priorità della funzione (come definita quando la funzione è stata originariamente agganciata)." Se non specificata, utilizza la priorità predefinita (10). Ovvero - Devi specificare la STESSA priorità con cui l'azione è stata aggiunta, per RIMUOVERE effettivamente l'azione.

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

Questa era la risposta che cercavo. Grazie :)

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

Questo è un trucco piuttosto rapido e sporco, ma un modo è creare una variabile globale come $my_plugin_name_saving e impostarla a true prima di chiamare wp_update_post e restituire se la variabile è già impostata.


<?php
/* Plugin Name: My plugin name */

$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 set 2022 02:33:54