Jak uniknąć nieskończonej pętli w wywołaniu zwrotnym save_post

12

Korzystałem z tej strony dużo do rozwiązywania moich problemów, ale tym razem nie udało mi się znaleźć i odpowiedzieć na mój problem.

Dostaję i nieskończoną pętlę, gdy używam wp_update_postwewnątrz wywoływanej funkcji save_post. Wiem, że jest to powszechny problem, ale nie mogę wymyślić, jak go uniknąć.

Chcę zapisać kolejność moich postów (które należą do sekcji „post”). Stworzyłem więc niestandardowe pole meta, które zawiera pewne sortowalne elementy HTML. W każdym elemencie znajduje się ukryty znacznik wejściowy o nazwie name = 'sectionorder []'. Kiedy klikam standardowy przycisk „Aktualizacja” WordPressa, tablica zawierająca wszystkie identyfikatory postów (w kolejności) jest wysyłana przez POST. Oto kod, w którym pobieram tablicę i chcę zapisać kolejność:

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

Problem polega jednak na tym, że uruchamia nieskończoną pętlę. Jak tego uniknąć? Może mogę to zrobić w zupełnie inny sposób?

Doceń swoją pomoc!

elgehelge
źródło

Odpowiedzi:

26

Możesz usunąć połączenie zwrotne z save_postzaczepu, zaktualizować post, a następnie ponownie dodać połączenie z powrotem do zaczepu. Codex podaje przykład .

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
źródło
Łał. Dziękuję za szybką odpowiedź. Działa jak marzenie! Nie wiem, dlaczego sam nie widziałem tego przykładu kodu
elgehelge
@Stephen, używam update_post_metaw funkcji zaczepionej do, czy save_postpowinienem po niej odczepić i ponownie zaczepić update_post_meta?
Anagio
Nie, update_post_metanie będzie (generalnie) przyczyną save_posturuchomienia.
Stephen Harris
Po marnowaniu godziny znalazłem to, a także zaoszczędziłem więcej godzin, dziękuję.
Manchumahara,
13

Nie mam reputacji do komentowania, więc dodam odpowiedź, mimo że Stephen jest doskonały i poprawny. Po prostu nie obsługuje instancji, gdy chcesz ustawić priorytet akcji.

Jeśli ustawisz priorytet podczas dodawania akcji, ale nie określisz priorytetu podczas jej usuwania, nadal otrzymasz nieskończoną pętlę.

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

// NIEPRAWIDŁOWY sposób na poradzenie sobie z tym - prowadzi do nieskończonej pętli

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

// PRAWY sposób na poradzenie sobie z tym - wykonuje się tylko raz

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
źródło
1
Wow dzięki! Oszalałem, próbując dowiedzieć się, dlaczego wciąż otrzymywałem nieskończoną pętlę, nawet podczas dodawania remove_action/add_action.
Banjer
1
WordPress Codex :: Plugin API / Action Reference / save post :: Unikanie nieskończonych pętli Pokazują to. Jeśli spojrzysz na WordPress Codex :: Odwołanie do funkcji / usuń akcję :: Użycie „Priorytet funkcji (zgodnie z definicją, kiedy funkcja została pierwotnie podpięta).” Jeśli nie zostanie określony, użyje domyślnego priorytetu (10). A / K / A - Musisz określić SAMY priorytet w momencie dodania akcji, aby AKTUALNIE usunąć akcję.
Michael Ecklund,
To była odpowiedź, której szukałem. Dziękuję :)
manuman94,