Как сделать автоинкрементный счетчик пользовательских типов постов в WordPress?

Ссылка скопирована
1 ответ

Есть пользовательский тип постов с идентификатором doc. Надо сделать добавляющийся автоматом при сохранении такого поста уникальный номер в поле title перед самим названием.
Пытаюсь сделать так:
Создал страницу id = 100 с контентом в виде числа, первоначальное значение "1". И при wp_insert_post_data считываю из нее контент, увеличиваю, записываю обратно, добавляю в название.
Это как я думаю оно должно работать. )На деле при добавлении кода в functions.php при попытке создать doc номер в странице не меняется, тайтл у нового поста не меняется.

add_filter('wp_insert_post_data', 'add_doc_num', 10, 2); function add_doc_num($data, $postarr) {     if ($data['post_type'] == 'doc' && $data['post_status'] != 'publish') {         $source_post_id = 100;         $source_post = get_post($source_post_id);         $current_content = $source_post->post_content;         $current_number = intval($current_content);         $new_number = $current_number + 1;         $updated_content = strval($new_number);         $source_post->post_content = $updated_content;         wp_update_post($source_post);          // Обновляем заголовок создаваемого поста         $data['post_title'] = $updated_content . ' ' . $data['post_title'];     }      return $data; }

add_filter('wp_insert_post_data', 'add_doc_num', 10, 2); function add_doc_num($data, $postarr) { if ($data['post_type'] == 'doc' && $data['post_status'] != 'publish') { $source_post_id = 100; $source_post = get_post($source_post_id); $current_content = $source_post->post_content; $current_number = intval($current_content); $new_number = $current_number + 1; $updated_content = strval($new_number); $source_post->post_content = $updated_content; wp_update_post($source_post); // Обновляем заголовок создаваемого поста $data['post_title'] = $updated_content . ' ' . $data['post_title']; } return $data; }

Где проблема, подскажите, пжлст.

Дополнительно:

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Редакция DevOps Ответ

Хранить счётчик в контенте отдельной страницы — плохая идея. Это неочевидно, может ломаться при автосохранениях, ревизиях и параллельных сохранениях. Для таких задач используйте option или отдельное meta-поле у самой записи.

Также в вашем условии есть логическая проблема: вы проверяете $data['post_status'] != 'publish'. То есть код срабатывает не для публикации, а для черновиков/автосохранений. При создании записи WordPress может несколько раз вызывать сохранение, поэтому номер легко получить не там, где ожидаете.

Безопаснее делать номер один раз на save_post_doc, пропускать автосохранения и проверять, что номер ещё не назначен.

add_action('save_post_doc', function ($post_id, $post, $update) {
    if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
        return;
    }
 
    if (get_post_meta($post_id, '_doc_number', true)) {
        return;
    }
 
    $number = (int) get_option('site_doc_counter', 0) + 1;
    update_option('site_doc_counter', $number, false);
    update_post_meta($post_id, '_doc_number', $number);
 
    remove_action('save_post_doc', __FUNCTION__, 10);
 
    wp_update_post([
        'ID' => $post_id,
        'post_title' => $number . ' ' . $post->post_title,
    ]);
}, 10, 3);

add_action('save_post_doc', function ($post_id, $post, $update) { if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) { return; } if (get_post_meta($post_id, '_doc_number', true)) { return; } $number = (int) get_option('site_doc_counter', 0) + 1; update_option('site_doc_counter', $number, false); update_post_meta($post_id, '_doc_number', $number); remove_action('save_post_doc', __FUNCTION__, 10); wp_update_post([ 'ID' => $post_id, 'post_title' => $number . ' ' . $post->post_title, ]); }, 10, 3);

Но в этом примере есть нюанс: __FUNCTION__ внутри анонимной функции не поможет корректно снять хук. Поэтому для боевого кода лучше использовать именованную функцию:

add_action('save_post_doc', 'site_add_doc_number', 10, 3);
 
function site_add_doc_number($post_id, $post, $update) {
    if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
        return;
    }
 
    if (get_post_meta($post_id, '_doc_number', true)) {
        return;
    }
 
    $number = (int) get_option('site_doc_counter', 0) + 1;
    update_option('site_doc_counter', $number, false);
    update_post_meta($post_id, '_doc_number', $number);
 
    remove_action('save_post_doc', 'site_add_doc_number', 10);
    wp_update_post([
        'ID' => $post_id,
        'post_title' => $number . ' ' . $post->post_title,
    ]);
    add_action('save_post_doc', 'site_add_doc_number', 10, 3);
}

add_action('save_post_doc', 'site_add_doc_number', 10, 3); function site_add_doc_number($post_id, $post, $update) { if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) { return; } if (get_post_meta($post_id, '_doc_number', true)) { return; } $number = (int) get_option('site_doc_counter', 0) + 1; update_option('site_doc_counter', $number, false); update_post_meta($post_id, '_doc_number', $number); remove_action('save_post_doc', 'site_add_doc_number', 10); wp_update_post([ 'ID' => $post_id, 'post_title' => $number . ' ' . $post->post_title, ]); add_action('save_post_doc', 'site_add_doc_number', 10, 3); }

Если номера юридически важные и не должны пропускаться, нужен более строгий механизм с отдельной таблицей и блокировкой. Для обычной нумерации документов в админке option + post meta обычно достаточно.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно