add action only on post publish – not update

I have action which adds meta field with value on post publish. Problem is that when I update post meta field is reset to default value.

I already tried ‘new_to_publish’ instead of ‘publish_post’ but it doesn’t work.

Read More
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');

}
}

Still can’t make it work

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

As I can understand it – every time status changes from pending to publish do whatever is inside if. But it doesn’t work.

In my site I have post rating system with meta field ‘votes_count’ where are stored votes. When I query votes_count from highest to lowest it doesn’t show posts with no votes, so I need to populate it with default value 0 to include them into query. Everything works fine but when i update votes are reset to 0… Posts are published by users with pending status which I check and publish.

Related posts

3 comments

  1. Like @milo pointed out in the comment, checking if the post meta exists is the easiest way to achieve what you want – like this:

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


    → On creation/publish not on updates

    I’m keeping this, because it fits the matter of doing things on publish and not on update. But auto-draft → publish only works on first publishing a post and only if a post gets published directly. There might be the need to cover more cases, for example draft → publish or pending → publish.

    You could try:

    //it's specific because you specify the hook like this {$old_status}_to_{$new_status}
    add_action( 'auto-draft_to_publish', 'wpse120996_specific_post_status_transition' );
    function wpse120996_specific_post_status_transition() { 
            //your code
    }
    

    instead of using new_to_publish.

    → Take a look at Post Status Transitions for additional information.

    Or you could work with the generic hook transition_post_status like this:

    //it's generic because you specify post statuses inside the function not via the hook
    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' ) {
            //your code
        }
    }
    

    Another neat method doing things on publish or to be exact first creation and not on updates would be going like shown below. I opted for using the save_post hook, but this could be done with the publish_post hook too.

    add_action('save_post', 'wpse120996_on_creation_not_update');
    function wpse120996_on_creation_not_update($post_id) {
        //get_post( $post_id ) == null checks if the post is not yet in the database
        if( get_post( $post_id ) == null ) {
            //your code
        }
    }
    
  2. This should work best:

    add_action( 'publish_post' , 'my_func' , 10 , 2 );
    function my_func( $ID , $post )
    {
      if ( $post->post_date != $post->post_modified )
      {
        //THIS IS AN UPDATE
      }
      else
      {
        //POST JUST GOT PUBLISHED
      }
    }
    
  3. Suprisingly it works. Maybe I’m not as stupid as I thought. Thank you both for help.

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

Comments are closed.