WordPress Codex suggests two ways of adding post meta to the response. I'm trying to achieve this with register_meta() since it kinda seems to be the correct way to me.
PROBLEM:
meta field in the response remains empty when I use register_meta() although show_in_rest is set to true.
SOLUTION:
Thanks to Allan Fuller, who pointed out, that the $object_type parameter (the first one in register_meta() function should be post and not the post type. This is also mentioned in the comments section of the new code reference
Description before solution
Here how am I doing this:
Step 1: call from functions.php:
\add_action('init', [$this, 'init'], 10); Step 2: register custom post type in the init function:
\register_post_type( CompanyPostType::POST_TYPE_NAME, [ 'labels' => [ 'name' => __('Companies'), 'singular_name' => __('Company') ], 'public' => true, 'show_in_rest' => true, 'rest_base' => CompanyPostType::REST_BASE, 'has_archive' => false, 'rewrite' => false, 'supports' => [ 'custom-fields', 'revisions' ] ] ); Step 3 - profit: register meta for the custom post type in the init function
$meta = [ 'key' => CompanyPostType::META_NAME, 'description' => 'Name of the company', 'type' => 'string' ], \register_meta(CompanyPostType::POST_TYPE_NAME, $meta['key'], [ 'show_in_rest' => true, 'single' => true, 'type' => $meta['type'], 'description' => $meta['description'], ] ); The meta field is still remains empty in the response. If I however use the second way also suggested in the codex (register_rest_field()) in the same init hook:
\add_action( 'rest_api_init', function () { \register_rest_field( CompanyPostType::POST_TYPE_NAME, CompanyPostType::META_NAME, array( 'get_callback' => function($params ) { $meta = \get_post_meta( $params['id'], CompanyPostType::META_NAME, true); return (string) $meta; }, ) ); } ); then the field with its value appears in the response. What am I missing?
Since I'm using a custom post type, it may be worth looking at this part of code as well. As stated in the codex, when registering it I set ‘supports’ => [‘custom-fields’] so that custom fields appear in the rest response. The whole looks like this:
return \register_post_type( self::POST_TYPE_NAME, [ 'labels' => [ 'name' => __('Companies'), 'singular_name' => __('Company') ], 'public' => true, 'show_in_rest' => true, 'rest_base' => self::REST_BASE, 'has_archive' => false, 'rewrite' => false, 'supports' => [ 'title', 'custom-fields', 'revisions' ] ] ); EDIT:
I tried, as suggested by Allan Fuller in his blog post, to put \register_meta() in rest_api_init hook, but it has no effect on meta in the response.
21 Answer
If you want to use register_meta to work, you have to explicitly hook it to rest_api_init
so for your example
add_action( 'rest_api_init', 'register_posts_meta_field' ); function register_posts_meta_field() { register_meta('post', $meta['key'], [ 'show_in_rest' => true, 'single' => true, 'type' => $meta['type'], 'description' => $meta['description'], ] ); } The above is untested but see working plugin version of code here
The object type needs to be 'post' to the custom post type name
first argument is object_type - valid object types are predefined by wordpress and CPT is a type of post
4