tools/rest-field-generator
WordPress REST API Field Generator
Add a field to an existing REST API response with register_rest_field(): a schema, a get_callback that reads the prepared array, and an update_callback that receives the real object.
snippet.php
/**
* Adds 'reading_time' to the 'post' REST response.
*
* The hook is 'rest_api_init'. A field registered on 'init' is registered too
* early to reach the response.
*
* Worth knowing before using this: a field that only reads one meta key is
* usually better registered with register_post_meta( ..., 'show_in_rest' =>
* true ), which exposes it under 'meta' and brings a type, a sanitizer and an
* auth rule with it. register_rest_field() is the right tool when the value is
* computed, when it joins several sources, or when it has to appear at the top
* level of the response rather than inside 'meta'.
*/
function wps_register_rest_fields() {
register_rest_field(
'post',
'reading_time',
array(
'get_callback' => 'wps_get_reading_time',
'update_callback' => 'wps_update_reading_time',
'schema' => array(
'type' => 'integer',
'context' => array( 'view', 'edit' ),
'description' => 'Estimated reading time in minutes.',
),
)
);
}
add_action( 'rest_api_init', 'wps_register_rest_fields' );
/**
* Reads the value for a response.
*
* The parameter is the *prepared response array*, not a WP_Post — that is
* core's choice, and it is why this reads $prepared['id'] rather than
* $post->ID. The latter fails at request time with "Attempt to read property
* ID on array".
*/
function wps_get_reading_time( $prepared ) {
return get_post_meta( $prepared['id'], 'reading_time', true );
}
/**
* Writes a value sent for this field.
*
* Note the asymmetry with the getter above, which is core's: update_callback
* receives the real object — a WP_Post for a post type — while get_callback
* receives an array.
*/
function wps_update_reading_time( $value, $post ) {
$updated = update_post_meta( $post->ID, 'reading_time', $value );
if ( false === $updated ) {
return new WP_Error(
'rest_field_not_updated',
__( 'Could not update the field.', 'text-domain' ),
array( 'status' => 500 )
);
}
return true;
}