Problem with WordPress “save_post” Action

I have developed a WordPress plugin which needs to perform additional processing when a post of a custom post type is saved.

The most logical solution was to utilise the “save_post” action. Upon being invoked the action handler either creates or updates a database record in a custom table (depending on whether “Create Post” or “Update Post” is clicked).

Read More

I have implemented this and it seemed to be working perfectly, but there is a minor issue which I would like to resolve. It seems that “save_post” is also triggered when loading the “Create Post” page for the first time (i.e. before any user inputs are entered and before the submit new/changes button is pressed).

This means that the custom database table is getting filled with one blank row for each new post that is saved. It also means that there is one blank row for each time the add post page is loaded.

Here is a simplified version of my “save_post” handler:

function do_save_post($post_id) {
    if (get_post_type($post_id) !== 'mycustomtype')
        return $post_id;

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
        return $post_id;

    if (!current_user_can('edit_mycustomtype'))
        return $post_id;

    echo 'This happens when selecting "Add New" from admin sidebar.';
    echo 'Even though post has not been saved or updated.';
    echo 'This should only happen when button on right of editor is clicked.';
}

How can I detect whether the post is actually being saved?

Related posts

Leave a Reply

4 comments

  1. I had this same problem and took a look at the relevant section of post.php. Turns out save_post is called every time post.php runs, so you’ll run it on post creation, list, etc.

    In WP 3.1, “post_updated” is called only on a save/create event in post.php. So I used:

    add_action('post_updated', 'some_function');
    

    Hope this works for you too.

  2. Using the ‘post_updated’ hook tends to be problematic, particularly when using custom post types. Instead, I used this as my solution:

       function do_save_post($post_id){
            $post = get_post($post_id);
            if($post->post_status == 'trash' or $post->post_status == 'auto-draft'){
                    return $post_id;
            }
            echo "do stuff";
        }
    

    I didn’t want to perform any actions when items were sent to the trash, either.

  3. This hook runs whenever a post or page is created or updated, which could be from an import, post/page edit form, xmlrpc, or post by email. So I’d guess it also runs when a post-revision is saved. If I where you I’d check if the postID is set (is the only argument the hook function should get) and if it is a revision wp_is_post_revision().