Cum să eviți bucla infinită în callback-ul save_post
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!

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

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

@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
?

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

Î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 );

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
.

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.

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');
