register_post_meta vs register_rest_field

23 dic. 2020
·
  • REST API
  • What is code
  • WordPress
·
  • metadatos
  • php
  • RES API

Existen maneras de registrar un campo o dato en la REST API y que aparezca en la respuesta de un post o un term pero las dos más directas son register_post_meta y register_rest_field. A veces pueden confundir porque sus parámetros son similares y porque pueden tener usos bastante parecidos.

register_post_meta

register_post_meta( $post_type, $meta_key, $args );

En realidad es un wrapper de register_meta, y siempre deberíamos usarla si queremos utilizar un metadato para un tipo de post. Es muy recomendable hacerlo porque le da consistencia a nuestros datos y los tendríamos mejor controlados. Además, con esta función podemos ser capaces de asignar un valor por defecto o una descripción al dato.

register_post_meta( 'page', 'my_meta_key', [
    'show_in_rest'      => true,
    'single'            => true,
    'type'              => 'string',
    'description'       => '...',
    'auth_callback'     => function() {...},
    'sanitize_callback' => function() {...},
] );

show_in_rest es el argumento que controla la visibilidad del campo en la REST API. Por defecto es false ya que WordPress considera que un metadato es privado a menos que se indique lo contrario. Si show_in_rest es true, el metadato aparecerá en la REST API, dentro del campo meta:

...
"meta": {
   ...
   "my_meta_key": "value"
}
...

En el atributo auth_callback se puede definir una función que se ejecutará cuando el metadato se inserta, actualiza o borra. Si la función devuelve false, el dato no se tocará.

'auth_callback' => function() {
   return current_user_can( 'edit_post' );
}

sanitize_callback , por su parte, sanitizará (no existe esa palabra pero es que higienizar suena fatal) el valor antes de ser guardado. Hay que tener en cuenta que esta función se ejecuta cuando update/add_post_meta son invocadas siempre justo antes de guardar en base de datos.

'sanitize_callback' => 'sanitize_text_field',

En este caso utilizamos la famosa sanitize_text_field que trae ya WordPress que elimina etiquetas de HTML de una cadena entre algunas cosas más.

register_rest_field

Con register_rest_field podemos conseguir algo parecido. Es una manera de añadir información extra a un post, y esto por definición también es un metadato, pero atañe exclusivamente a la REST API. En realidad un REST Field, puede estar adscrito a un metadato y actualizarlo o hacer lo que se quiera con él pero esto una forma más específica de registrar datos que se adscriben exclusivamente a un objeto en la REST API y que ni siquiera tienen que tener representación en la Base de Datos.

register_rest_field( $object_type, $attribute, $args )

En este caso, un campo de la REST API, se relaciona con un $object_type, que no es un tipo de post, sino uno de las abstracciones típicas en WordPress: post, term o comment. De esta manera se puede mostrar un campo extra en la REST API en cualquiera de estos tres.

register_rest_field( 'post', 'my_rest_field', [
	'get_callback' => function( $object ) {...},
	'update_callback' => function() {...},
	'schema'       => [
		'description' => 'Field description',
		'type'        => 'string',
		'context'     => [ 'view' ],
	],
] );

De forma similar a register_post_meta, la lista de argumentos tiene un par de callbacks para controlar la recogida y modificación del valor del campo. El campo en sí no significa nada ya que no hay ningún registro en Base de Datos asociado a él pero con estas dos funciones le daremos un sentido.

get_callback será la encargada de entregar el valor del campo. Dentro de ella podríamos sacar el dato o calcularlo como quisiéramos, desde un metadato a incluso algo dentro de una tabla de MySQL personalizada que hayamos creado en un plugin. Recibe un array $object con el post, term o comment. Por ejemplo:

'get_callback' => function( $object ) {
	return is_main_author( $object['post_author'] )
},

Le pasamos el valor a una función que ya tenemos creada que identifica si un usuario es un autor principal del sitio, sea lo que signifique eso. Si sólo dejáramos esta función, el campo no sería editable de ninguna manera por lo que sería un campo de sólo lectura.

'update_callback' => function ( $value, $object, $field_name ) {
	if ( $value ) {
		update_post_meta( $object->ID, 'a_meta_key', true );
	} else {
		delete_post_meta( $object->ID, 'a_meta_key', true );
	}
},

En este ejemplo, utilizando update_callback, cuando se llame a la REST API actualizando el post, se puede pasar el valor del campo para cambiarlo también. En este caso, simplemente es la actualización de un metadato pero se podría actualizar una entrada, un comentario o cualquier otra cosa.

¿Cuándo uno y cuándo el otro?

Esta entrada venía motivada por el hecho de la confusión que siempre aparece cuando tengo que registrar un dato para Gutenberg. Muchas veces empiezo registrando un metadato con register_post_meta pero luego acabo cambiándolo a register_rest_field porque veo que no se trata sólo de un metadato sino de algo que necesita una lógica algo más compleja al rescatar el dato o actualizarlo.

En mi opinión la regla es que si simplemente quieres sacar y actualizar un metadato, utiliza register_post_type y si tu campo necesita varias comprobaciones o calcular el dato de distintas maneras, utiliza register_rest_field. Puede parecer obvio pero cuando nos enfrentamos al código no parece tan claro.