· 1 min read
update_post_meta does not fire save_post
I built a feature that links the same hymn across different hymn books. It keeps a lookup table in an option and rebuilds it on the save_post hook, so the table is always current.
Then I corrected some lyrics with a script, and the table stopped being current.
The catch
The lyrics live in post meta. My script called update_post_meta(), which writes the meta and fires its own meta hooks. It doesn’t fire save_post, because the post itself wasn’t saved.
Edit a post on the screen and everything works, since the editor saves the post. Change the same value from a script, an import or WP-CLI, and anything hanging off save_post never hears about it.
What to do about it
If your code derives something from post meta, you have two options.
Hook the meta write as well:
add_action( 'updated_post_meta', function ( $meta_id, $post_id, $key ) {
if ( 'hymn' === $key ) {
my_rebuild_map();
}
}, 10, 3 );
That fires once per changed row, so on a bulk import you’d rebuild thousands of times. For a bulk job it’s cheaper to do what I did and call the rebuild once, at the end of the script.
Either way, the rule is worth remembering. save_post means a post was saved, and it doesn’t mean the data changed.