node-wpapi icon indicating copy to clipboard operation
node-wpapi copied to clipboard

Add a guide for "how to work with meta"

Open nezzard opened this issue 7 years ago • 13 comments

Hi, i tried to update post meta, when i created posts, but nothing happened It's possible with node-wpapi? wp.song().create({ title: '1', content: 'Your post content', status: 'publish', meta: {key: 'youtube', value: '12'}, }).then(function( response ) { console.log( response.id ); })

nezzard avatar Dec 19 '16 09:12 nezzard

On the WordPress side of things you'll need to set things up so that you can read and post meta. See http://v2.wp-api.org/extending/modifying/#read-and-write-a-post-meta-field-in-post-responses

bigandy avatar Dec 19 '16 11:12 bigandy

A better option these days is to use first-party meta support, introduced in 4.6, detailed here in this API status update post and further explained in the README from the pull request for meta handling

kadamwhite avatar Dec 20 '16 06:12 kadamwhite

@kadamwhite is there some change I have a meta field upvote for my custom post and I have registered using register_meta() , as suggested and when I use a get request , I am getting the meta values like..

  "meta": {
    "upvote": "4",
    "downvote": "0"
  }

When I try to update it works via postman if I pass the body as

{ "meta": {
    "upvote": "5"
} }

But the node-wpapi does not take this, if I pass it as

{
meta:{
key:'upvote'
value: '4'
}}

It does not update the values.

chattes avatar Mar 02 '17 21:03 chattes

Merging #286 into this issue; documenting how to work with custom meta is currently our top-priority docs issue

kadamwhite avatar Jul 11 '17 15:07 kadamwhite

When you create/update post, you pass meta object, for example:

wpapi.posts().create( {
	title: 'Your Title',
	content: ' Your content',
	status: 'publish',
	meta: {
		custom_meta_key: 'something'
	}
} ).then( function( response ) {
	// whatever
} );

On the server side, you must use register_meta(). If you are using custom post type, the post type must have custom-fields support (see documentation for $args['supports'] of register_post_type(). That is documented for REST API.

But if you are using meta with custom role, your role should also have edit_post_meta (and delete_post_meta if you are deleting) capability. See code for WP_REST_Meta_Fields::update_meta_value() and WP_REST_Meta_Fields::delete_meta_value(). I haven't seen that this is documented anywhere so I figured it out during debugging.

dimadin avatar Oct 25 '17 13:10 dimadin

@dimadin Sorry, but could You be more specific, where exactly on server side I should change something to get meta work?

sculpt0r avatar Feb 21 '18 13:02 sculpt0r

Messed with the same problem, being total noob in wordpress infrastructure. Solved by putting

register_meta('post', 'duration', [
  'type' => 'integer',
  'description' => 'duration',
  'single' => true,
  'show_in_rest' => true,
]);

into functions.php of theme. This unlocked me:

meta: { duration: 123 }

dmdb avatar Jun 15 '18 10:06 dmdb

@Calemb @dmdb In WordPress 5.0 note that this will change to register_post_meta( 'post', ... -- the snippet you have here will register "duration" for all custom post types. (You'd change 'post' to 'my_cpt' if you want duration to apply to a custom post type). We will be releasing a comprehensive update to our meta handling documentation on the REST API handbook in conjunction with 5.0.

kadamwhite avatar Jun 23 '18 17:06 kadamwhite

I've been struggling for a few days and finally found how to deal with it. I added two meta fields to comment meta, which are "likes" and "pin". To enable POST request from frontend like reactjs, I need to add "likes" and "pin" to REST API. This is how I add and update data: Since I am very new to Wordpress and PHP, I spent most of the time finding out why comment meta is not updating through update_comment_meta. It turns out that I need to access the comment id through $comment_object->comment_ID not $comment_object->ID. So, make sure you are familiar with the type you are working on.

function slug_register_comment_meta() {
    register_rest_field( 'comment',
        'likes',
        array(
            'get_callback'    => 'slug_get_comment_meta',
            'update_callback' => 'slug_update_comment_meta',
            'schema'          => array('likes' => 'The number of likes received in this comment.'),
        )
    );
    register_rest_field( 'comment',
        'pin',
        array(
            'get_callback'    => 'slug_get_comment_meta',
            'update_callback' => 'slug_update_comment_meta',
            'schema'          => array('pin' => 'If this comment is pinned or not.'),
        )
    );
}

function slug_get_comment_meta( $comment_object, $field_name, $request ) {
  return get_comment_meta( $comment_object['id'], $field_name , true );
}

function slug_update_comment_meta( $value, $comment_object, $field_name ) {
  return update_comment_meta( $comment_object->comment_ID, $field_name, wp_slash( $value ) );
}
add_action( 'rest_api_init', 'slug_register_comment_meta' );

I only test the code with curl in my terminal:

curl -X POST http://website.com/wp-json/wp/v2/comments -H 'content-type: application/json' -d '{"post": 1, "content":"comment meta test", "author_name":"name", "author_email":"[email protected]", "likes":"1000", "pin":"1"}'

b02902032 avatar Jul 14 '18 14:07 b02902032

Responding to some prior questions in this thread, @chattes you should be using the same structure in Postman as in this library, so I'm unclear on why you believed you needed to separate the key and value. If you have registered meta, you'd update it as,

.update( {
    meta: {
        upvote: 5,
    }
} )

@b02902032 What you have there looks like it works (and I assure you, even seasoned contributors get confused by the inconsistent property naming!) For a post, page, or other custom post type resource though I'd stick with register_post_meta over register_rest_field unless you need to derive the data from something other than post meta.

kadamwhite avatar Oct 21 '19 21:10 kadamwhite

Here's how to add a boolean meta field to tags and posts.

function prefix_register_meta_fields()
{
    $term_types = ['post_tag'];
    $post_types = ['post'];

    $key = 'the_example_key';
    $args = [
        'type' => 'boolean',
        'description' =>
            'An the_example_key boolean value.',
        'single' => true,
        'show_in_rest' => true
    ];

    foreach ($post_types as $type) {
        register_post_meta($type, $key, $args);
    }
    foreach ($term_types as $type) {
        register_term_meta($type, $key, $args);
    }
}

add_action('rest_api_init', 'prefix_register_meta_fields');

And then update it on some post of your choosing.


wp.tags()
        .id(TAG_ID)
        .update({
            meta: {
               the_example_key : true
            }
        })

wp.posts()
        .id(POST_ID)
        .update({
            meta: {
               the_example_key : true
            }
        })

tomatrow avatar Apr 06 '20 06:04 tomatrow

How do you add multiple meta values with the same key? Using a single object only allows attaching of 1 meta key.

CyberCyclone avatar Jul 14 '20 01:07 CyberCyclone

I did not find an example of what to do if you need to add several values for one key. I try in wp register_meta( 'post', 'reader', array( 'show_in_rest' => true, 'single' => false, 'type' => 'string', )); i add meta in wp-api wp.posts().id( 32477 ).update({ title: 'A Better Title', slug:"kukusik-100", status: 'draft', meta:{ reader:'Anton Petrov,Oleg Arno', } }).then(function( response ) { console.log( response.id ); }) And I get in the post meta fields the following reader:'Anton' reader:'Petrov' reader:'Oleg' reader:'Arno' I would like to see there reader:'Anton Petrov' reader:'Oleg Arno'

ProvokatorDark avatar Jul 02 '21 11:07 ProvokatorDark