Cum să eviți bucla infinită în callback-ul save_post

7 mai 2012, 13:21:14
Vizualizări: 16.2K
Voturi: 22

Am folosit acest site mult pentru a-mi rezolva problemele, dar de data aceasta nu am reușit să găsesc un răspuns la problema mea.

Am o buclă infinită atunci când folosesc wp_update_post în interiorul unei funcții apelate de save_post. Știu că aceasta este o problemă comună, dar nu reușesc să înțeleg cum să o evit.

Vreau să salvez ordinea postărilor mele (care sunt de tipul 'section'). Am creat o cutie meta personalizată care conține elemente HTML sortabile. În fiecare element există un tag input ascuns cu name='sectionorder[]'. Când apăs butonul standard WordPress 'Update', un array care conține toate ID-urile postărilor (în ordine) este trimis via POST. Iată codul în care preiau array-ul și încerc să salvez ordinea:

    // Actualizează ordinea secțiunilor
$sectionorder = $_POST['sectionorder'];
if (isset($sectionorder)) { // Evită eroarea dacă nu există secțiuni adăugate încă
    foreach( $sectionorder as $no => $sectionID ) {
        $post_update = array();
        $post_update['ID'] = $sectionID;
        $post_update['menu_order'] = $no;
        wp_update_post( $post_update );
    }
}

Problema este că începe o buclă infinită. Cum pot evita acest lucru? Poate că există o altă metodă complet diferită de a face asta?

Apreciez ajutorul tău!

0
Toate răspunsurile la întrebare 3
5
44

Puteți elimina callback-ul din hook-ul save_post, actualizați postarea și apoi adăugați din nou callback-ul la hook. Codex oferă un exemplu.

add_action('save_post', 'wpse51363_save_post');

function wpse51363_save_post($post_id) {

    // Verifică dacă nu este o rutină de auto-salvare
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
          return;

    // Efectuează verificări de permisiuni! De exemplu:
    if ( !current_user_can('edit_post', $post_id) ) 
          return;

    // Verifică nonce-ul!

    // Dacă apelezi wp_update_post, scoate acest funcție din hook pentru a evita bucla infinită
    remove_action('save_post', 'wpse51363_save_post');

    // apelează wp_update_post, care va chema save_post din nou. De exemplu:
    wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));

    // adaugă din nou funcția în hook
    add_action('save_post', 'wpse51363_save_post');
}
7 mai 2012 13:43:21
Comentarii

Wow. Mulțumesc pentru răspunsul rapid. Funcționează perfect! Nu știu de ce nu am văzut eu acel exemplu de cod..

elgehelge elgehelge
7 mai 2012 14:08:23

@Stephen, eu folosesc update_post_meta într-o funcție legată la save_post. Ar trebui să deconectez și să reconectez după update_post_meta?

Anagio Anagio
14 nov. 2013 21:20:55

Nu, update_post_meta nu va declanșa (în general) save_post.

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

După ce am pierdut o oră, am găsit acest lucru și mi-a mai salvat câteva ore, mulțumesc.

Manchumahara Manchumahara
22 dec. 2019 07:39:16

funcționează pentru mine, în anul 2020

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

Încă nu am destulă reputație pentru a comenta, așa că adaug un răspuns chiar dacă cel al lui Stephen este excelent și corect. Doar că nu tratează cazurile în care dorești să setezi prioritatea acțiunii.

Dacă setezi prioritatea atunci când adaugi acțiunea, dar nu o specifici când o elimini, vei obține totuși o buclă infinită.

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

// Modul GREȘIT de a gestiona acest lucru - duce la buclă infinită

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

// Modul CORECT de a gestiona acest lucru - se execută doar o singură dată

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 iun. 2014 21:05:37
Comentarii

Wow, mulțumesc! Începeam să înnebunesc încercând să înțeleg de ce tot primeam bucla infinită, chiar și după ce am adăugat remove_action/add_action.

Banjer Banjer
25 aug. 2014 03:27:25

WordPress Codex :: Plugin API/Action Reference/save post :: Evitarea buclelor infinite Ei demonstrează asta. Dacă te uiți la WordPress Codex :: Function Reference/remove action :: Utilizare "Prioritatea funcției (așa cum a fost definită când funcția a fost legată inițial)." Dacă nu este specificată, folosește prioritatea implicită (10). Altfel spus - Trebuie să specifici ACEEAȘI prioritate ca atunci când acțiunea a fost adăugată, pentru a ELIMINA cu adevărat acțiunea.

Michael Ecklund Michael Ecklund
2 dec. 2016 18:50:11

Acesta este răspunsul pe care îl căutam. Mulțumesc :)

José Manuel Blasco José Manuel Blasco
6 iun. 2019 12:34:05
0

Acesta este un truc rapid și murdar, dar o modalitate este de a crea o variabilă globală precum $my_plugin_name_saving și de a o seta la true înainte de a apela wp_update_post, apoi de a returna dacă variabila este deja setată.


<?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 sept. 2022 02:33:54