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.

Ive been looking into actions and hooks etc... from wordpress, but cant seem to do a very simple thing. I just want to execute a function whenever a post is updated, and within the function I want the names of the terms that have been changed on that save. So maybe some sort of before and after comparison of terms??

Could somebody please just give me a hint at the direction to go in? I started off with:

add_action('save_post', 'myFunction');

But I cant seem to pass the before and after taxonomy terms to it for a comparison to see which have just been selected.. if that makes sense.

Thanks :)

share|improve this question

2 Answers 2

up vote 1 down vote accepted

After WordPress has updated a posts' taxonomy terms it triggers the action:


(see source) which passes 6 variables:

  1. Object ID
  2. Terms that were assigned to the post (or added depending on 5) (could be their slug or term ID).
  3. Taxonomy-term IDs of above (not term IDs)
  4. The taxonomy
  5. Append. If true - terms in 2 are added to existing terms. If false (default) terms replace the existing terms.
  6. The post's terms before updating (as taxonomy-term IDs)

Problem 1

Unfortunately there is no way of knowing if that object refers to post, or something (like a user). That might be a way hooking onto set_object_terms only when you can be sure that when its next fired, it refers to a post.

Problem 2

The IDs are passed are taxonomy-term IDs, not term-IDs - and most WordPress functions use the term ID. So you'll probably need to get the term ID (and taxonomy) from the taxonomy term ID to do anything useful. A potential work around is, since we know the taxonomy, list all the terms and do a simple foreach loop and filter them. Better suggestions are welcome

The following is untested.


 function wpse61678_terms_changed($object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids){

      //Note problem 1 - we might not necessarily know what $object_id refers to. 

     //Added terms are specified terms, that did not already exist
     $added_tt_ids = array_diff($tt_ids, $old_tt_ids);

     if( $append ){
         //If appending terms - nothing was removed
         $removed_tt_ids = array();
         //Removed terms will be old terms, that were not specified in $tt_ids
         $removed_tt_ids = array_diff($old_tt_ids, $tt_ids);

    /*Note problem 2, we would preferably like the term objects / IDs, 
      Currently we have the taxonomy term IDs*/

    //Get all terms
    $all_terms = get_terms( $taxonomy, array('hide_empty'=>0));

    $removed_terms =array()
    $added_terms =array();
    foreach( $all_terms as $term ){
         $tt_id = (int) $term->term_taxonomy_id;
         if( in_array( $tt_id, $removed_tt_ids) ){
             $removed_terms[] = $term;
         }elseif( in_array( $tt_id, $added_tt_ids) ){
             $added_terms[] = $term;

    //$added_terms contains added term objects
    //$removed_terms contains removed term objects

share|improve this answer
Thanks so much for the lengthy reply! I did try using set_object_terms, but came into trouble when I kept getting "missing argument" php errors pointing to the line of the function with all the parameters in.. I thought I was doing it wrong but I did what u have done above. The $object_id worked fine, but nothing else??? –  JamesG Aug 13 '12 at 14:58
Yup, needed to set the number of arguments explicitly to 6. Updated now :). –  Stephen Harris Aug 13 '12 at 15:15
YES!!! That is it!! Thank you so much :) I cant believe I didnt read the docs carefully enough to realise you had to specify that. Thought I was going insane lol. THANKS! –  JamesG Aug 13 '12 at 15:26

If there are potential problems with using the set_object_terms hook as pointed out by Stephen, possibly hooking into pre_post_update and then followed by wp_insert_postwould suffice,

function get_terms_before_update(){
    $terms_before = get_the_terms( $id, $taxonomy );
    //do something else if required...
    return $terms_before; 

    function get_terms_after_update(){
    //pass in $terms_before from get_terms_before_update() function
    //compare terms
share|improve this answer
+1. This probably a more reliable solution. You could make into a class and store the variables as a class variable. wp_insert_post could be replaced with save_post. –  Stephen Harris Aug 13 '12 at 15:19

Your Answer


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.