Как избежать бесконечного цикла в обратном вызове save_post

12

Я много раз использовал этот сайт для решения своих проблем, но на этот раз мне не удалось найти и ответить на мою проблему.

Я получаю и бесконечный цикл при использовании wp_update_postвнутри функции, которая вызывается save_post. Я знаю, что это общая проблема, но я не могу понять, как этого избежать.

Я хочу сохранить порядок своих постов (который относится к типу поста 'section'). Поэтому я создал собственный мета-блок, содержащий некоторые сортируемые html-элементы. В каждом элементе есть скрытый тег ввода с именем = 'sectionorder []'. Поэтому, когда я нажимаю на стандартную кнопку «Обновить» WordPress, массив, содержащий все идентификаторы сообщений (по порядку), отправляется через POST. Итак, вот код, где я извлекаю массив и хочу сохранить порядок:

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

Но проблема в том, что он запускает бесконечный цикл. Как мне этого избежать? Может быть, я могу сделать это совершенно по-другому?

Оцените вашу помощь!

elgehelge
источник

Ответы:

26

Вы можете удалить обратный вызов из save_postловушки, обновить сообщение и затем повторно добавить обратный вызов в ловушку. Кодекс дает пример .

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');
}
Стивен Харрис
источник
Вау. Спасибо за быстрый ответ. Работает как шарм! Не знаю, почему я сам не видел этот пример кода ...
elgehelge
@ Стефен, я использую update_post_metaфункцию, к которой save_postя должен также отцепиться и снова зацепиться update_post_meta?
Анагио
Нет, update_post_metaне будет (в общем случае) причиной save_postсрабатывания.
Стивен Харрис
Потратив час, нашел это, и это также сэкономило больше часов, спасибо.
Манчумахара
13

У меня не достаточно репутации, чтобы комментировать, поэтому я добавляю ответ, хотя Стивен отличный и правильный. Он просто не обрабатывает экземпляры, когда вы хотите установить приоритет действия.

Если вы устанавливаете приоритет при добавлении действия, но не указываете приоритет при удалении, вы все равно получите бесконечный цикл.

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

// НЕПРАВИЛЬНЫЙ способ справиться с этим - приводит к бесконечному циклу

remove_action('save_post', 'wpse51363_save_post');
wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));
add_action('save_post', 'wpse51363_save_post');

// ПРАВИЛЬНЫЙ способ справиться с этим - выполняется только один раз

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 );
Чарльз Хаймет
источник
1
Вау, спасибо! Я сходил с ума, пытаясь понять, почему я все еще получал бесконечный цикл, даже при добавлении remove_action/add_action.
Banjer
1
WordPress Codex :: Plugin API / Справочник по действию / сохранить сообщение :: Как избежать бесконечных циклов Они демонстрируют это. Если вы посмотрите на WordPress Codex :: Function Reference / remove action :: Usage «Приоритет функции (как определено, когда функция была перехвачена).» Если не указан, используется приоритет по умолчанию (10). A / K / A - Вы должны указать тот же самый приоритет, как и при добавлении действия, для того, чтобы АКТУАЛЬНО удалить действие.
Майкл Эклунд
Это ответ, который я искал. Спасибо :)
manuman94