Como evitar loop infinito no retorno de chamada save_post

12

Eu tenho usado muito este site para resolver meus problemas, mas desta vez não consegui encontrar e responder ao meu problema.

Eu recebo um loop infinito ao usar wp_update_postdentro de uma função que é chamada save_post. Sei que esse é um problema comum, mas não consigo descobrir como evitá-lo.

Quero salvar a ordem das minhas postagens (que é do tipo 'seção'). Então, eu criei uma meta box personalizada que contém alguns elementos html classificáveis. Em cada elemento, há uma tag de entrada oculta com name = 'sectionorder []'. Então, quando clico no botão 'Atualizar' padrão do WordPress, uma matriz contendo todos os IDs das postagens (em ordem) é enviada via POST. Então, aqui está o código em que recupero a matriz e quero salvar o pedido:

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

Mas o problema é que ele inicia um loop infinito. Como evito isso? Talvez eu possa fazer isso de uma maneira completamente diferente?

Aprecie sua ajuda!

elgehelge
fonte

Respostas:

26

Você pode remover o retorno de chamada do save_postgancho, atualizar a postagem e adicionar novamente a chamada ao gancho. O Codex dá um exemplo .

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
fonte
Uau. Obrigado pela resposta rápida. Funciona como um encanto! Não sei porque eu não vi esse exemplo de código mim ..
elgehelge
@ Stephen, eu uso update_post_metaem uma função ligada a save_posteu também devo soltar e voltar a soltar depois update_post_meta?
Anagio
Não update_post_meta(geralmente) não causará o save_postdisparo.
Stephen Harris
Depois de perder uma hora, encontrei isso e isso também economizou mais horas, obrigado.
Manchumahara
13

Ainda não tenho a reputação de comentar, por isso estou adicionando uma resposta, mesmo que a de Stephen seja excelente e correta. Ele simplesmente não lida com instâncias quando você deseja definir a prioridade da ação.

Se você definir a prioridade ao adicionar a ação, mas não especificar a prioridade ao removê-la, ainda obterá um loop infinito.

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

// A maneira errada de lidar com isso - leva ao 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');

// A maneira correta de lidar com isso - executa apenas uma vez

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
fonte
1
Uau, obrigado! Eu estava enlouquecendo tentando descobrir por que ainda estava obtendo o loop infinito, mesmo ao adicionar remove_action/add_action.
Banjer
1
WordPress Codex :: Plugin API / Referência de Ação / save post :: Evitando loops infinitos Eles demonstram isso. Se você olhar no WordPress Codex :: Referência de Função / remover ação :: Uso "A prioridade da função (conforme definida quando a função foi originalmente conectada)." Se não especificado, ele usa a prioridade padrão (10). A / K / A - Você deve especificar a MESMA prioridade como quando a ação foi adicionada, para remover REALMENTE a ação.
Michael Ecklund
Esta é a resposta que eu estava procurando. Obrigado :)
manuman94