Comment éviter la boucle infinie dans le rappel save_post

12

J'utilise beaucoup ce site pour résoudre mes problèmes, mais cette fois je n'ai pas réussi à trouver et à répondre à mon problème.

J'obtiens et boucle infinie lors de l'utilisation à l' wp_update_postintérieur d'une fonction qui est appelée save_post. Je sais que c'est un problème courant, mais je ne sais pas comment l'éviter.

Je veux sauvegarder l'ordre de mes messages (qui est du type "section"). J'ai donc créé une méta-boîte personnalisée qui contient des éléments html triables. Dans chaque élément, il y a une balise d'entrée cachée avec name = 'sectionorder []'. Ainsi, lorsque je clique sur le bouton standard de mise à jour de WordPress, un tableau contenant tous les ID des messages (dans l'ordre) est envoyé via POST. Voici donc le code où je récupère le tableau, et souhaite enregistrer la commande:

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

Mais le problème est qu'il démarre une boucle infinie. Comment puis-je éviter cela? Peut-être que je peux le faire d'une manière complètement différente?

Appriciez votre aide!

elgehelge
la source

Réponses:

26

Vous pouvez supprimer le rappel du save_postcrochet, mettre à jour le message, puis rajouter le rappel au crochet. Le Codex donne un exemple .

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
la source
Sensationnel. Merci pour la réponse rapide. Fonctionne comme un charme! Je ne sais pas pourquoi je n'ai pas vu cet exemple de code moi-même.
elgehelge
@Stephen, j'utilise update_post_metadans une fonction accrochée à save_postdois-je également décrocher et recrocher après update_post_meta?
Anagio
Non, update_post_metane provoquera pas (généralement) save_postle déclenchement.
Stephen Harris
Après avoir perdu une heure, j'ai trouvé cela et cela a également sauvé plus d'heures, merci.
Manchumahara
13

Je n'ai pas vraiment la réputation de commenter, donc j'ajoute une réponse même si Stephen's est excellent et correct. Il ne gère tout simplement pas les instances lorsque vous souhaitez définir la priorité de l'action.

Si vous définissez la priorité lors de l'ajout de l'action mais ne spécifiez pas la priorité lorsque vous la supprimez, vous obtiendrez toujours une boucle infinie.

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

// La mauvaise façon de gérer cela - conduit à une boucle infinie

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 bonne façon de gérer cela - s'exécute une seule fois

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
la source
1
Ouah merci! Je devenais fou en essayant de comprendre pourquoi j'obtenais toujours la boucle infinie, même lors de l'ajout remove_action/add_action.
Banjer
1
WordPress Codex :: Plugin API / Action Reference / save post :: Éviter les boucles infinies Ils le démontrent. Si vous regardez WordPress Codex :: Function Reference / remove action :: Usage "La priorité de la fonction (telle que définie lorsque la fonction a été initialement accrochée)." S'il n'est pas spécifié, il utilise la priorité par défaut (10). A / K / A - Vous devez spécifier la même priorité que lorsque l'action a été ajoutée, afin de réellement supprimer l'action.
Michael Ecklund
C'est la réponse que je cherchais. Merci :)
manuman94