DEV Community

David Woolf
David Woolf

Posted on • Originally published at indexforwp.com on

Modify WordPress REST routes with register rest field

Getting Started

The register_rest_field function is a PHP function that allows you to add extra fields to any registered endpoint (posts, pages, custom post types, terms, users, etc). The function takes three parameters:

register_rest_field(
    $object_type,
    $attribute,
    $args
);
Enter fullscreen mode Exit fullscreen mode

The $object_type parameter is any data type in WordPress, and can be an array of multiple types, or a string for a single type. Next, the $attribute parameter is the name of the field you want to register and will show up in the rest response as the key name.

Finally, the $args parameter is an array with a getter, setter, and schema definition. All three arguments are optional, so you have a lot of flexibility in how you control your field.

Registering a field

Let’s build a real example. In this case we’re going to register a field for posts that shows how many “slaps” the post has, along with a setter to add slaps whenever the user clicks a “slap this post” button.

First we want to target posts and name our attribute:

add_action('rest_api_init', function() {
    register_rest_field(
        'post',
        'slap_count',
        // ... getters and settings
    );
});
Enter fullscreen mode Exit fullscreen mode

Note: wrap your register_rest_field calls in the rest_api_init action to ensures the rest api is loaded

Getting the value

While the above is the only required code to use the register_rest_field function, the field won’t show up in your REST endpoint without at least a get value. Let’s take care of that now:

add_action('rest_api_init', function() {
    register_rest_field(
        'post',
        'slap_count',
        // NEW CODE
        array(
            'get_callback' => function($object) {
                $slap_count = get_post_meta( $object['id'], 'slap_count', true );

                return $slap_count ? $slap_count : 0;
            }
        )
    );
});
Enter fullscreen mode Exit fullscreen mode

The get_callback argument accepts an $object parameter, which in this case is an individual post (passed as an array). Inside of the callback we can use standard WordPress functions like get_post_meta. In this case, we are grabbing the slap_count meta field and returning either the value or 0.

If you query an single post using the /wp-json/wp/v2/posts/<id> endpoint, you should see this line in the response:

"slap_count": 0 // or whatever the value is
Enter fullscreen mode Exit fullscreen mode

For our example, the field so far is pretty useless but if you just wanted to output a value directly then the above is all you need.

Setting the value

To allow updates to the value, add a update_callback argument to the $args array:

add_action('rest_api_init', function() {
    register_rest_field(
        'post',
        'slap_count',
        array(
            'get_callback' => function($object) {
                $slap_count = get_post_meta( $object['id'], 'slap_count', true );

                    return $slap_count ? $slap_count : 0;
            },
            // NEW CODE
            'update_callback' => function ( $value, $object ) {
                    $slap_count = get_post_meta( $object->ID, 'slap_count', true );

                    update_post_meta( $object->ID, 'slap_count', $slap_count + 1 );
            },
        )
    );
});
Enter fullscreen mode Exit fullscreen mode

The update_callback function takes two parameters: $value and $object. In our case we aren’t using the value variable, but instead just adding 1 to the value whenever the callback is fired.

Note: in this function $object is passed as an object type instead of an array like get_callback.

Triggering an update

To actually fire the update_callback function, simply call the /wp-json/wp/v2/posts/<id> endpoint with the POST method, and pass the field name through the body as JSON:

// Javascript example
fetch('/wp-json/wp/v2/posts/1', {
    // make sure to authenticate or pass the X-WP-Nonce value as a header
    method: 'POST',
    body: JSON.stringify({
        "slap_count": 1 // reminder that the value doesn't matter for our example as we just increment the count by one
    })
})
.then(response => response.json())
.then(data => {
    // ... the updated post object is returned here
})
.catch(error => console.log('error', error));
Enter fullscreen mode Exit fullscreen mode

Securing your field

As always, a little security goes a long way. The third parameter in the register_rest_field $args array is a schema array with sanitization and validation options:

add_action('rest_api_init', function() {
    register_rest_field(
        'post',
        'slap_count',
        array(
            // ...get_callback
            // ...update_callback

            // NEW CODE
            'schema' => array(
                'type' => 'string' // the type of value we expect to be passed back
                'sanitize_callback' => function($value) {
                    // run sanitization here
                    },
                    'validate_callback' => function ($value) {
                            // run sanitization here
                    },
            )
        )
    );
});
Enter fullscreen mode Exit fullscreen mode

The schema parameter takes three arguments:

  • the type of the value (int, string, boolean, etc)
  • A sanitization callback to sanitize the input
  • A validate callback to make sure it conforms to some set of rules

If you haven’t already, read more on sanitizing and validating values accepted into your rest routes here. The same options can be used in the schema callback functions.

Wrap Up

In just a few lines of code, you can completely customize WordPress’ built-in REST routes with your own data. Or combine and extend existing values to avoid unnecessary work in Javascript and prevent multiple REST calls to grab necessary data.

Author

david_woolf image

Discussion (0)