Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

When you create a plugin and set up a process function, Wordpress will run the plugin process function twice upon clicking the update button. I believe the first process is for the versioning (revision) post, and the second the actual post.

Now, I've got an INSERT function in my process, so it is now inserting the data twice.

What is the best way to ensure that processing doesn't happen while creating the revision and and only on the actual post processing?

* Note: Targeting Wordpress 3.0+ *

An Example (complete plugin):

<?php
/*
Plugin Name: Something Amazing
Plugin URI: http://www.somewhere.com/
Description: Displays something.
Author: Some guy
Version: 1.0
Author URI: http://www.somewhere.com/
*/
function call_something() {
 return new something();
}
if (is_admin()) add_action('load-post.php','call_something');

class something {

 public function __construct() {
  add_action('add_meta_boxes',array(&$this,'something_add_boxes'));
  add_action('save_post',array(&$this,'something_process'),1,1);
 }

 public function something_add_boxes() {
  add_meta_box('something','Some Thing',array(&$this,'something_form'),'post','side','default');
 }

 public function something_form($post,$args) {
  echo '<p><input type="text" name="somethingnew" /></p>';
 }

 public function something_process($id) {
  echo 'hey there! I\'m going to cause a redirect warning, but you will see this line twice per submit!';
  //do_something_amazing();
 }
}
?>

Perhaps there is a better hook to use to process that doesn't make it write twice?

share|improve this question
    
I've stuck in simple code in the process function that works, but there must be a flag or something in the Wordpress framework: function process() {global $post, $wthtwice; if ($wthtwice) return; $wthtwice = true; –  Exit Jul 12 '11 at 21:02

5 Answers 5

up vote 3 down vote accepted

@Steve Functions hook to save_post are always called twice, Wordpress call functions hooked to save_post twice because:

  • first time it saves the post revision.
  • second time it saves the actual post.

NOTE: If you have disabled post revisions using define('WP_POST_REVISIONS', false); then the save_post hook will be fired only once when the actual post will be saved.

I just tested the following code and it works as expected and the echo only runs once in the something_process function.

NOTE: the way I have hooked to save_post

<?php
/*
Plugin Name: Something Amazing
Plugin URI: http://www.somewhere.com/
Description: Displays something.
Author: Some guy
Version: 1.0
Author URI: http://www.somewhere.com/
*/
function call_something() {
 return new something();
}
if (is_admin()) add_action('load-post.php','call_something');

class something {

 public function __construct() {
  add_action('add_meta_boxes',array(&$this,'something_add_boxes'));
  add_action('save_post',array(&$this,'something_process'),1,2);
 }

 public function something_add_boxes() {
  add_meta_box('something','Some Thing',array(&$this,'something_form'),'post','side','default');
 }

 public function something_form($post,$args) {
  echo '<p><input type="text" name="somethingnew" /></p>';
 }

 public function something_process($id, $post_object) {
    // don't run the echo if this is an auto save
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
        return;

    // don't run the echo if the function is called for saving revision.
    if ( $post_object->post_type == 'revision' )
        return;

  echo 'hey there! I\'m going to cause a redirect warning, but you will see this line twice per submit!';
  //do_something_amazing();
 }
}
?>
share|improve this answer
    
Thanks, that is exactly it. This works perfectly, and appears to use everything within the WP framework. –  Exit Jul 23 '11 at 23:58

You need make sure that your code is only being run when the post is saved and not when a revision or automatic save is being carried out.

Check if the current post id is indeed an actual post an not a revision or autosaved post by doing this (the actual post will always return a FALSE value):

if ( is_int( wp_is_post_revision( $id ) ) )
    return;

if( is_int( wp_is_post_autosave( $id ) ) )
    return;
share|improve this answer

you can avoid autosave using a simple check in your function, something like

if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return '';
    }

update

Like i've posted, just add the above snippet to the very top of your something_process function before any thing else.

share|improve this answer
    
i just went over the question again and seeing your code would help to identify the cause of the 2nd process. –  Bainternet Jul 12 '11 at 22:03
    
sample code for what? link? –  Bainternet Jul 12 '11 at 22:45
    
The sample code provided by Wordpress has this same problem: codex.wordpress.org/Function_Reference/add_meta_box The class version. I'll put a generalized version above. –  Exit Jul 12 '11 at 22:46
    
The limit was 5 minutes to edit, hitting enter submitted prematurely, blame Facebook for the silly enter = submit nonsense. –  Exit Jul 12 '11 at 22:47
    
the code on the codex doesn't run twice , tested it about a 100 times, its probably something else in your code. –  Bainternet Jul 12 '11 at 22:51

In my plugins I do a verification of the status of post is a revision. You can do something like this in the "something process" function.

public function something_process($id, $post) {
    if ($post->post_type == 'revision') return;
    echo 'hey there! I\'m going to cause a redirect warning, but you will see this line twice per submit!';
    //do_something_amazing();
}

Adding the if ($post->post_type == 'revision') return; line, you "cancel" the first call of function on WP.

You need to do a second change on the action hook too. Just change the line:

add_action('save_post',array(&$this,'something_process'),1,1);

to this:

add_action('save_post',array(&$this,'something_process'),1,2);

Like this you pass the second parameter on action "save_post" (the $post variable)

share|improve this answer
    
Hi, thanks, but that also isn't working. I tried that method before, but I did some checking and during both passes, it never sets the post_type to 'revision' when it is in the process function. Both times is registers the same post type, which seems odd. Did you try running this plugin to see if it works? It might be not working do to a bug in WP. –  Exit Jul 13 '11 at 1:57
    
Here in my lab website works.. What is your WP version? –  Caio Alves Jul 15 '11 at 13:11

I hear you're looking for the "best" way... well that depends. Code needs to handle custom issues- just like you wouldn't select a cadillac to go offroad, and you wouldn't (probably) take a jeep to a night at the opera.

I have a plugin that handles both processes run on save on purpose. I use a static var and conditionally select which code I want to run. I also test for post parent id using the wp_is_post_revision() function above, and and have greater flexibility in tailoring conditions to meet my needs exactly based on those results.

function complex_meta_update_on_save($id){
$ppid = wp_is_post_revision($id);
(can also employ) if($post_parent_id === false) $ppid = $id;
...set environmentals...

static $tc;
if($tc < 1){
execute conditions essential  for revisions, or preprocess for ppid 
}
//note no else-
i can do stuff here that is ok to duplicate, processing, etc. 

if($tc > 0) {
execute conditions and statements essential for post parents
update custom tables with custom queries, register newly processed taxonomies, et. al. 
keep in mind, on Save hook, post data has been saved in db. My plugin uses special  
metadata that needs to know whether I've got a revision, or the parent. 
update_post_meta($id, $blah);now is ok to use $id in
}
//oh the staticness of it all
$tc++;
}//end function

I don't know that any of that is brilliant, or even the best idea, it's just what works where I need- and I don't have to manage many more hooks than edit and save... pretty simple in one regard.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.