Search code examples
wordpresspluginspublishslug

Wordpress publish_post fires too often


I am writing a plugin that simply sends subscribers emails when new post is published(so it shouldn't send any emails when it's on pending, updating, or draft, etc)

In the plugin definition I have:

add_action('plugins_loaded', 'setup_plugin_actions');

function setup_plugin_actions(){
  if(has_action('new_to_publish')){
    $simple_email_subscriber = new email_subscriber();

    add_action('new_to_publish', $simple_email_subscriber->email_subscribers());
  }
}

And in my email_subscribers method I have:

class email_subscriber(){
  function email_subscribers(){
    //get post information
    $post = get_post($post_id);

    $post = get_post( $post_id );
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return false;

    if(wp_is_post_revision($post->ID) || wp_is_post_autosave($post->ID)) return;

    //email code
    ......
  }
}

A very simple code that just trying to add an action listener to the publish_post method.

However, since publish_post does fire so often, I was getting 8 emails whenever I made an update, new publish, or even if I just stay on the wordpress page and it does auto updates.

I was trying to find some callback that only happens when a new post is truly made: new_to_post

Doesn't work at all.

Can someone help me?

Cheers Phil


Solution

  • The reason you are getting so many emails is because you are not adding the action properly, explained below. As it stands now, you are actually calling your function to send the emails lots of times and hooking the result of the function to the action (which doesn't really do anything), instead of hooking the function to the action.

    Your add_action has a couple of issues - you are adding your method to the transition new_to_publish action (which fires only when a post status is "new" and changes to "publish") and not publish_post which will catch posts that are published from any status, and the method you are passing is invalid - the argument is a string for a function or array if it is a method on an object with the first element being the object and the second being the function. It should look like:

    add_action('publish_post', array($simple_email_subscriber, 'email_subscribers') );
    

    Your function is also not taking the $post_id as an argument, so it will never know what post to load. Your definition should be:

    function email_subscribers($post_id){ /* your code */ }
    

    You are also calling $post = get_post( $post_id ); twice in your function which isn't necessary, but if you want to make sure that this function only runs when a post's status is publish no matter how it is called, add:

    $post = get_post( $post_id );
    if ($post->post_status != "publish") return;