I am updating one of my plugins for Gutenberg. I need to check for the presence of a custom post meta field when a post is updated or published, so I’ve hooked into publish_post
:
function process_meta( $ID, $post ) {
if (get_post_meta($ID, 'my_post_meta_field', true)) {
// do something
}
}
add_action('publish_post', 'process_meta', 10, 2);
The problem is that post meta fields have not yet been saved to the database when this hook (or any others that I’m aware of) fires, so unless a post draft has already been saved, my_post_meta_field
always appears empty at this point in my code.
In the old version of my plugin, I would simply check the contents of the $_POST[]
array. However, Gutenberg now saves content directly via the WordPress API, so there is no POST
data to intercept.
How can I work around this problem?
The solution is to use a different hook which fires after post meta data has been saved by Gutenberg to the WP API. After reading this related discussion on Github and inspecting this code by n7studios, I discovered that rest_after_insert_post
is a hook to use.
So, the way to reliably check for the existence of a WordPress Post Meta field when using Gutenberg:
function read_my_meta_field( $post, $request ) {
$my_meta_field = get_post_meta($post->ID, 'my_post_meta_field', true);
// Process $my_meta_field as desired...
}
add_action('rest_after_insert_post', 'read_my_meta_field', 10, 2);
Note that you can handle meta fields from other post types by simply changing post
in the first parameter to the add_action()
function, so instead of using 'rest_after_insert_post'
you would use 'rest_after_insert_whatever'
.
Finally, here is a more complete answer to my own question, which checks the meta field only on post publication.
function run_on_post_publication( $ID, $post ) {
// Only register this hook if we really are publishing a new post
add_action('rest_after_insert_post', 'read_my_postmeta_field', 10, 2);
}
add_action('publish_post', 'run_on_post_publication', 10, 2);
function read_my_postmeta_field( $post, $request ) {
$my_meta_field = get_post_meta( $post->ID, 'my_post_meta_field', true);
// Process $my_meta_field as desired...
}
For reference, if you want more control over when, exactly, your code runs, check out the ‘transition_post_status’ hook.