# 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.

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.

• Some counter questions: 1. Are you sure if you got your post statuses right? 2. I know - from yesterdays question - this is about the rating system you implemented - is the only thing you are trying to make sure that there is a value returned or echoed? – Nicolai Nov 2 '13 at 16:05
• why not just use your first example but check if the meta data already exists first and only add it if it doesn't? – Milo Nov 2 '13 at 16:10
• I query post by votes_count with meta_key="votes_count" and meta_value="meta_value_num" and today I realized that queries don't show posts with no votes. I checked database and there meta fields named votes_count have only posts with 1 or more votes. So I came into conclusion that meta fields are created when user votes and next step in my thinking was to auto create meta field votes_count with value 0 for every new post. That Im trying to make with this function. I tried to edit code from yesterday but with no luck. – th3rion Nov 2 '13 at 16:15
• @milo you're absolutely right – Nicolai Nov 2 '13 at 16:18
• I didnt answer questions. 1. Im pretty sure with statuses - when user creates post its "pending" and I publish it after checking 2. I think I already answered it. – th3rion Nov 2 '13 at 16:19

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-draftpublish 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 draftpublish or pendingpublish. 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' ) {
}
}


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 } }  • Thank you for help. I thought about such conditional earlier but it was not logical for my that empty or '' equals not exist. I thought that meta field with '' (or empty as you wrote the code) exists but has no value. – th3rion Nov 2 '13 at 16:56 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');

}
}

}


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
}
}

• this does not work the first time a post has been updated, after the initial publish. – sarcastasaur Aug 24 at 3:58