Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm not entirely sure this is Wordpress' fault, but I figure I'd ask anyway and see if anyone else has experienced any problems like this before.

I'm trying to save an array to a wp_options table row. The data is coming from a custom metabox and is being saved when the save_post hook is triggered. I assumed this should do the trick:

update_option("myOptionName", $myArray);

I started getting 4(?!) of each value I saved. For instance:

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

Needless to say, this behavior is extremely annoying. It works perfectly well with strings, but never arrays. I've tried to get around this by trying json_encode to store it as a string-y entity, but even that isn't working. The problem could very well be the legacy code I've inherited by taking on this project, but I see nothing pointing to save_post.

Has anyone ever seen a situation like this before?

EDIT: As requested ... the save function:

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

}
share|improve this question

4 Answers 4

save_post is called multiple times while you edit a post (autosave). That's a common gotcha, but it'd be cool if you can post your function's code to see whats going on.

share|improve this answer
    
Edited my original comment to include it. –  Akamaozu Aug 24 '12 at 12:34

Like MZAweb said it's (probably) the auto save.
You should edit your code that when the hooks triggers it checks for auto save:

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
}
share|improve this answer
    
I have it in there. Autosave doesn't trigger this. It happens only when I get it to submit and it adds exactly 3 more of the current item being saved to the array. For example, first save results in: array([0]=>"option1", [1]=>"option1", [2]=>"option1", [3]=>"option1"); On save two: array([0]=>"option1", [1]=>"option1", [2]=>"option1", [3]=>"option1", [4]=>"option1", [5]=>"option1", [6]=>"option1", [7]=>"option1"); –  Akamaozu Aug 24 '12 at 13:33
    
It appears that save_post action is triggered multiple times in Wordpress, according to wordpress.org/support/topic/save_post-called-repeatedly. I don't know how true that is, but it really explains the level of weirdness I'm experiencing ... –  Akamaozu Aug 24 '12 at 16:03
1  
you could prevent it with named array keys, it won't add them then –  janw Aug 25 '12 at 7:02

As you recreate the whole array each time from reading it, I would just erase the option before creating it again :

$newView[] = $_REQUEST['postID'];
delete_option( 'ci_guidesbrick_posts' );
update_option('ci_guidesbrick_posts', $newView ); 
share|improve this answer

I had something similar going on when I tried to use the wp_editor() function while inside a custom metabox. It was wanting to save multiple times.

Take a look at this.

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

}

Look at line #43. See how I had to remove_action the original function... run the update... and then add_action back again?

That may be what you need to do as well.

Here is a quick "example" code:

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');
}
share|improve this answer
    
You might be on to something here! Unfortunately the code base where I experienced this problem is no longer my responsibility, so I'll set up a test to see if this solution works for me or not. Thanks for your reply! –  Akamaozu Oct 24 '13 at 13:43
    
You're welcome! Yeah, I'd be interested to hear your results. –  josh Oct 24 '13 at 16:20
    
Please don't use third party services to host code. Add it directly to your posts. Thank you :-) –  Pieter Goosen Dec 7 at 6:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.