web-dev-qa-db-fra.com

La mise à jour de wp_options avec un tableau sur save_post entraîne la duplication d'entrées

Je ne suis pas tout à fait sûr que ce soit la faute de Wordpress, mais je pense que je demanderais quand même et que quelqu'un d'autre a déjà rencontré des problèmes de ce type.

J'essaie de sauvegarder un tableau sur une ligne de la table wp_options. Les données proviennent d'une métabox personnalisée et sont en cours de sauvegarde lorsque le hook save_post est déclenché. J'ai supposé que cela devrait faire l'affaire:

update_option("myOptionName", $myArray);

J'ai commencé à obtenir 4 (?!) De chaque valeur sauvegardée. Par exemple:

$myArray = array("option1");
update_option("myOptionName", $myArray);
get_option("myOptionName"); 
// array([0]=>"option1", [1]=>"option1", [2]=>"option1", [3]=>"option1");

Inutile de dire que ce comportement est extrêmement agaçant. Cela fonctionne parfaitement avec les chaînes, mais jamais les tableaux. J'ai essayé de contourner cela en essayant json_encode de le stocker en tant qu'entité string-y, mais même cela ne fonctionne pas. Le problème pourrait très bien être le code hérité dont j'ai hérité en prenant ce projet, mais je ne vois rien qui pointe vers save_post.

Est-ce que quelqu'un a déjà vu une telle situation auparavant?

EDIT: Comme demandé ... la fonction de sauvegarde:

# SAVE BRICK DATA
function brick_update() {

// Verify if this is an auto save routine.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
    return;
}

// Check permissions
if ( !current_user_can( 'publish_posts' ) ) { // Check for capabilities
    wp_die( 'Sorry, you do not have the capabilities access to this page. :(' );
}

if (!wp_verify_nonce($_REQUEST['brickupdate'], 'brickupdate')) {
    return;
}

$newView = array();
$currentView = get_option('ci_guidesbrick_posts');

if (!is_array($currentView)) {
    $currentView = (array)$currentView;
}

for (var i = 0, i < count($currentView), i++) {
    $newView[i] = $currentView[i];
}

$newView[] = $_REQUEST['postID'];

update_option('ci_guidesbrick_posts', $newView );   

}
3
akamaozu

J'ai eu quelque chose de similaire lorsque j'ai essayé d'utiliser la fonction wp_editor() dans une métabox personnalisée. Il voulait sauver plusieurs fois.

Regarde ça.

// SAVE Metabox for admin response
add_action('post_updated', 'display_jwl_wp_etickets_response_meta_box_save');
function display_jwl_wp_etickets_response_meta_box_save( $post_id ){


        if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
                return;
        if( !isset( $_POST['jwl_wp_etickets_editor_box_nonce_check'] ) || !wp_verify_nonce( $_POST['jwl_wp_etickets_editor_box_nonce_check'], 'jwl_wp_etickets_editor_box_nonce' ) )
                return;

        global $post;
        $post_type_object = get_post_type_object( $post->post_type );
        if ( !current_user_can( $post_type_object->cap->edit_post, $post->ID ) ) {
                return;
        }

        //$values = get_post_custom( $post_id );

        $editor_id = 'jwl_wp_etickets_response_editor';
        $meta_key = 'jwl_wp_etickets_response_box_select';

        $content_post = get_post($post_id);
        $old_content = $content_post->post_content;

        if(isset($_POST[$editor_id]) && !empty($_POST[$editor_id])) {
                if ( !wp_is_post_revision( $post_id ) ){ //IMPORTANT - Can cause infinite loop otherwise : codex - wp_update_post  (see note a few lines down)

                        $new_content = '<div class="eMember_admin_div"><p class="eMember_adminname_response"><strong>Admin</strong> on <strong>'.date('F j, Y @ g:i a').'</strong> said:</p>'.$_POST[$editor_id].'</div>';

                        $update_content = array(
                                'ID'           => $post_id,
                                'post_content' => $new_content.$old_content
                        );
                        // IMPORTANT!!!!
                        //*****
                        //*****  Apparently the 'post_updated' action likes to fire on every WP process while saving the content.
                        //*****  Since we are also firing on 'wp_update_post'; we are getting stuck in a loop.
                        //*****  To get around, unhook the function before sending the revised content with 'wp_update_post'.
                        //*****  This will prevent clashes between 'post_updated' and 'wp_update_post" firing at the same time.
                        //*****  DAMN YOU WORDPRESS!!
                        //*****
                        // Unhook this function so it doesn't loop infinitely
                        remove_action('post_updated', 'display_jwl_wp_etickets_response_meta_box_save');

                                // Update the post, which calls save_post again
                                wp_update_post( $update_content );
                                // Let's check the 'ticket state', and if queued... let's update it to 'in progress'
                                $terms_types = wp_get_post_terms( $post->ID, 'jwl_wp_etickets_states');
                                foreach ($terms_types as $term_type) {
                                        if ($term_type == 'Queued' || !empty($term_type)) {
                                                wp_set_post_terms( $post_id, __('In Progress','wp_etickets_lang'), 'jwl_wp_etickets_states' );
                                        }
                                }
                                // Do the same for post meta for cool admin filtering
                                update_post_meta( $post_id, 'jwl_wp_etickets_states_box_select', __('In Progress','wp_etickets_lang'), __('Queued','wp_etickets_lang') );

                        // Re-hook this function
                        add_action('post_updated', 'display_jwl_wp_etickets_response_meta_box_save');
                }
        }  

}

Regardez la ligne 43. Voyez comment j'ai dû remove_action la fonction d'origine ... lancer la mise à jour ... puis add_action à nouveau?

C'est peut-être ce que vous devez faire aussi.

Voici un "exemple" de code rapide:

add_action('post_updated', 'my_metabox_save');
function my_metabox_save() {
    // Run checks

    // Unhook this function so it doesn't loop infinitely
    remove_action('post_updated', 'my_metabox_save');

    // Run your update stuff

    // Re-hook this function
    add_action('post_updated', 'my_metabox_save');
}
1
josh

Au fur et à mesure que vous recréez le tableau entier à chaque lecture, je voudrais simplement effacer l'option avant de la recréer:

$newView[] = $_REQUEST['postID'];
delete_option( 'ci_guidesbrick_posts' );
update_option('ci_guidesbrick_posts', $newView ); 
0
Simon

save_post est appelé plusieurs fois lors de la modification d'une publication (sauvegarde automatique). C'est un piège commun, mais ce serait bien si vous pouviez poster le code de votre fonction pour savoir ce qui se passait.

0
MZAweb

Comme MZAweb l'a dit, c'est (probablement) la sauvegarde automatique.
Vous devriez éditer votre code de sorte que, lorsque les crochets se déclenchent, il vérifie la sauvegarde automatique:

add_action('save_post', 'my_save_post', 10, 2);
function my_save_post($post_id, $post) {
    // stop on autosave
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ){
        return;
    }
    // do your magic
}
0
janw