Обновление wp_options с массивом на save_post приводит к дублированию записей

Я не совсем уверен, что это ошибка WordPress, но я полагаю, что я все равно спрошу и посмотрю, не испытал ли кто-нибудь еще таких проблем раньше.

Я пытаюсь сохранить массив в строке таблицы wp_options. Данные поступают из пользовательского метаболизма и сохраняются при срабатывании hook_post. Я предполагал, что это должно сделать трюк:

update_option("myOptionName", $myArray); 

Я начал получать 4 (!) Каждого значения, которое я сохранил. Например:

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

Излишне говорить, что это поведение крайне раздражает. Он отлично работает со строками, но никогда не массивами. Я попытался обойти это, попробовав json_encode, чтобы сохранить его как объект string-y, но даже это не работает. Проблема может быть вполне унаследованным кодом, который я унаследовал, взяв этот проект, но я не вижу ничего, указывающего на save_post.

Кто-нибудь видел такую ​​ситуацию раньше?

EDIT: в соответствии с запросом … функция сохранения:

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

Solutions Collecting From Web of "Обновление wp_options с массивом на save_post приводит к дублированию записей"

save_post вызывается несколько раз, когда вы редактируете сообщение (автосохранение). Это обычная игра, но было бы здорово, если бы вы могли опубликовать код своей функции, чтобы узнать, что происходит.

Как MZAweb сказал, что это (возможно) автоматическое сохранение.
Вы должны отредактировать свой код, который, когда крючки запускает его, проверяет автоматическое сохранение:

 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 } 

Когда вы каждый раз воссоздаете весь массив, читая его, я просто удалю этот параметр перед его созданием:

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

У меня было что-то подобное, когда я пытался использовать wp_editor() находясь в пользовательском метабоксе. Он хотел спасти несколько раз.

Взгляните на это.

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

Посмотрите на строку # 43. Посмотрите, как мне пришлось remove_action из исходной функции … запустите обновление … а затем add_action снова?

Это может быть и то, что вам нужно делать.

Вот быстрый «пример» кода:

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