Leave a Reply

2 comments

  1. The update_post_meta hooks are called from the more generic update_metadata() function, so you might not have found it directly. The three hooks are:

    • update_post_metadata, a filter which allows you to “hijack” the metadata update and do something else. If you hook up a function that returns a boolean, execution stops there and the boolean is returned.
    • update_post_meta, an action that gets called before the data is updated in the database.
    • updated_post_meta, an action that gets called after the data is updated in the database.

    If the meta key did not exist in the database yet, update_metadata() passes control to add_metadata(), which has the similar hooks add_post_metadata, add_post_meta, and added_post_meta. This happens before update[d]_post_meta gets called. So if you want to do something when the meta key is added or updated, be sure to hook into both the update* and the add* hooks – but notice that while the updated_* and added_* actions pass similar parameters, update_* and add_* do not (add_post_meta does not pass a meta ID first).

    delete_metadata() has similar hooks: delete_post_metadata, delete_post_meta and deleted_post_meta.

    Sample code:

    add_action( 'added_post_meta', 'wpse16835_after_post_meta', 10, 4 );
    add_action( 'updated_post_meta', 'wpse16835_after_post_meta', 10, 4 );
    function wpse16835_after_post_meta( $meta_id, $post_id, $meta_key, $meta_value )
    {
        if ( 'wpse16835_meta_key' == $meta_key ) {
            wpse16835_do_something( $post_id, $meta_value );
        }
    }
    
    add_action( 'deleted_post_meta', 'wpse16835_deleted_post_meta', 10, 4 );
    function wpse16835_deleted_post_meta( $deleted_meta_ids, $post_id, $meta_key, $only_delete_these_meta_values )
    {
        if ( 'wpse16835_meta_key' == $meta_key ) {
            wpse16835_undo_something( $post_id );
        }
    }
    
  2. Jan answer covers pretty much it above except for the case where a custom metadata is deleted from the Edit Post page. This happens asynchronously as soon as you click on the “Delete” button under the metadata, via a call to wp-admin/admin-ajax.php. Unfortunately, that calls bypass the delete_metadata() function in meta.php and calls delete_meta() in wp-admin/includes/post.php instead (not to be confused with wp-includes/post.php).

    There are 2 actions that can still be used though, delete_postmeta (before deletion), and deleted_postmeta (after deletion). Both accept a single parameter $mid, which is the ID of the metadata (not the key). You can retrieve the metadata object using:

    $meta = get_post_meta_by_id($mid);  
    

    which returns an object with meta_id, post_id, meta_key abd meta_value. Of course, by the time deleted_postmeta is called the metadata has been deleted so get_post_meta_by_id() won’t work (which kinda makes that action useless)

    Same goes for updating a custom metadata from the Edit Post page. The update_metadata() function (and its actions) in meta.php is not called, but the update_meta() function in wp-admin/includes/post.php is instead. Two actions again here, update_postmeta and updated_postmeta. The args are $meta_id, $post_id, $meta_key, $meta_value.