Добавить действие только при публикации записи - не при обновлении

2 нояб. 2013 г., 17:21:08
Просмотры: 31.1K
Голосов: 10

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

Я уже пробовал использовать 'new_to_publish' вместо 'publish_post', но это не работает.

add_action('publish_post', 'add_custom_field_automatically');
function add_custom_field_automatically($post_ID) {
  global $wpdb;

  if(!wp_is_post_revision($post_ID)) {
    update_post_meta($post_ID, 'votes_count', '0');
  }
}

Всё еще не работает

add_action( 'transition_post_status', 'wpse120996_post_status_publish', 10, 3 );
function wpse120996_post_status_publish( $new_status, $old_status, $post_ID ) { 
    if ( $new_status == 'publish' && $old_status == 'pending' ) {
          global $wpdb;

  if(!wp_is_post_revision($post_ID)) {
    update_post_meta($post_ID, 'votes_count', '0');
    }
}}

Как я понимаю - каждый раз, когда статус меняется с "ожидающего" на "опубликовано", должно выполняться то, что находится внутри условия if. Но это не работает.

На моем сайте есть система рейтинга записей с произвольным полем 'votes_count', где хранятся голоса. Когда я делаю запрос votes_count от большего к меньшему, он не показывает записи без голосов, поэтому мне нужно заполнить их значением по умолчанию 0, чтобы включить их в запрос. Всё работает нормально, но когда я обновляю запись, голоса сбрасываются до 0... Записи публикуются пользователями со статусом "ожидающие", которые я проверяю и публикую.

5
Комментарии

Несколько встречных вопросов: 1. Вы уверены, что правильно определили статусы записей? 2. Я знаю из вчерашнего вопроса, что это касается вашей системы рейтинга - вы просто пытаетесь убедиться, что возвращается или выводится какое-то значение?

Nicolai Grossherr Nicolai Grossherr
2 нояб. 2013 г. 18:05:46

Почему бы просто не использовать ваш первый пример, но сначала проверить, существует ли метаданные, и добавлять их только если их нет?

Milo Milo
2 нояб. 2013 г. 18:10:01

Я делаю запрос постов по votes_count с meta_key="votes_count" и meta_value="meta_value_num", и сегодня понял, что запросы не показывают посты без голосов. Я проверил базу данных и увидел, что метаполя votes_count есть только у постов с 1 или более голосами. Поэтому я пришел к выводу, что метаполя создаются, когда пользователь голосует. Следующим шагом в моих рассуждениях было автоматическое создание метаполя votes_count со значением 0 для каждого нового поста. Это я и пытаюсь сделать с помощью этой функции. Я пробовал редактировать код со вчерашнего дня, но без успеха.

th3rion th3rion
2 нояб. 2013 г. 18:15:01

@milo ты абсолютно прав

Nicolai Grossherr Nicolai Grossherr
2 нояб. 2013 г. 18:18:19

Я не ответил на вопросы. 1. Я почти уверен насчет статусов - когда пользователь создает пост, он имеет статус "pending" (ожидает проверки), и я публикую его после проверки 2. Кажется, я уже ответил на это.

th3rion th3rion
2 нояб. 2013 г. 18:19:02
Все ответы на вопрос 3
1

Как отметил @milo в комментарии, проверка существования мета-поля записи — это самый простой способ достичь желаемого. Вот пример:

add_action('publish_post', 'wpse120996_add_custom_field_automatically');
function wpse120996_add_custom_field_automatically($post_id) {
    global $wpdb;
    $votes_count = get_post_meta($post_id, 'votes_count', true);
    if( empty( $votes_count ) && ! wp_is_post_revision( $post_id ) ) {
        update_post_meta($post_id, 'votes_count', '0');
    }
}




→ При создании/публикации, но не при обновлениях

Я оставляю это, потому что это соответствует теме выполнения действий при публикации, а не при обновлении. Но переход auto-draftpublish работает только при первой публикации записи и только если запись публикуется напрямую. Возможно, потребуется охватить больше случаев, например, draftpublish или pendingpublish.

Можно попробовать так:

//специфично, потому что хук указывается в формате {$old_status}_to_{$new_status}
add_action( 'auto-draft_to_publish', 'wpse120996_specific_post_status_transition' );
function wpse120996_specific_post_status_transition() { 
        //ваш код
}

вместо использования new_to_publish.

→ Подробнее смотрите в Post Status Transitions.

Или можно работать с общим хуком transition_post_status следующим образом:

//универсально, потому что статусы указываются внутри функции, а не через хук
add_action( 'transition_post_status', 'wpse120996_generic_post_status_transition', 10, 3 );
function wpse120996_generic_post_status_transition( $new_status, $old_status, $post ) { 
    if ( $new_status == 'publish' && $old_status == 'auto-draft' ) {
        //ваш код
    }
}


Ещё один аккуратный способ выполнения действий при публикации или, точнее, при первом создании, а не при обновлениях — использовать подход, показанный ниже. Я выбрал хук save_post, но это можно сделать и с помощью хука publish_post.

add_action('save_post', 'wpse120996_on_creation_not_update');
function wpse120996_on_creation_not_update($post_id) {
    //get_post( $post_id ) == null проверяет, есть ли запись в базе данных
    if( get_post( $post_id ) == null ) {
        //ваш код
    }
}
2 нояб. 2013 г. 17:38:01
Комментарии

Спасибо за помощь. Я думал о таком условии раньше, но для меня было нелогично, что пустое или '' означает "не существует". Я считал, что метаполе с '' (или пустое, как вы написали в коде) существует, но не имеет значения.

th3rion th3rion
2 нояб. 2013 г. 18:56:08
1

Это должно работать лучше всего:

add_action( 'publish_post' , 'my_func' , 10 , 2 );
function my_func( $ID , $post )
{
  if ( $post->post_date != $post->post_modified )
  {
    //ЭТО ОБНОВЛЕНИЕ
  }
  else
  {
    //ЗАПИСЬ ТОЛЬКО ЧТО ОПУБЛИКОВАНА
  }
}
25 мар. 2017 г. 03:55:36
Комментарии

это не работает при первом обновлении записи после первоначальной публикации.

sarcastasaur sarcastasaur
24 авг. 2019 г. 06:58:37
0

Удивительно, но это работает. Возможно, я не настолько глуп, как думал. Спасибо вам обоим за помощь.

add_action('publish_post', 'add_custom_field_automatically');
function add_custom_field_automatically($post_ID) {

global $wpdb;

$meta_count = get_post_meta($post_ID, "votes_count", true);
if($meta_count == '') {
if(!wp_is_post_revision($post_ID)) {
    update_post_meta($post_ID, 'votes_count', '0');

}
}

}
2 нояб. 2013 г. 18:51:02