Cómo obtener meta datos personalizados de posts usando la API REST
Estoy tratando de crear APIs REST para mi sitio web WordPress que se usa para listar instalaciones usando el plugin WordPress Job Manager.
He registrado mi post personalizado y taxonomías en \plugins\rest-api\plugin.php.
La siguiente API me devuelve todos los listados con la respuesta predeterminada.
http://localhost/sports/wp-json/wp/v2/joblisting/
Quería agregar meta datos del post en la respuesta JSON usando el siguiente código.
function slug_register_phone_number() {
register_rest_field( 'job_listing',
'phone',
array(
'get_callback' => 'slug_get_phone_number',
'update_callback' => null,
'schema' => null,
)
);
}
function slug_get_phone_number($post, $field_name, $request) {
return get_post_meta($post->id, '_phone' );
}
}
Usando el código anterior puedo agregar "phone" como una respuesta REST pero siempre obtengo phone = false en la respuesta. No está mostrando los datos correctos de la tabla wp_postmeta.
He seguido los enlaces mencionados a continuación como referencia.
http://v2.wp-api.org/extending/modifying/
Detalles de los plugins: 1. WP Job Manager 2. rest-api
Cualquier ayuda será realmente útil.

La API de WordPress tiene un filtro rest_prepare_post
(o rest_prepare_CPT
si estás trabajando con tipos de contenido personalizados) que puedes usar para modificar la respuesta JSON.
En tu caso sería rest_prepare_joblisting
.
function filtrar_json_joblisting( $data, $post, $context ) {
$phone = get_post_meta( $post->ID, '_phone', true );
if( $phone ) {
$data->data['phone'] = $phone;
}
return $data;
}
add_filter( 'rest_prepare_joblisting', 'filtrar_json_joblisting', 10, 3 );
Usando el mismo filtro también puedes eliminar campos/datos de la respuesta y hacer cualquier manipulación de los datos.

$post
en la función de callback es un array, no un objeto. Por lo tanto no puedes usar $post->id
. Cámbialo a $post['id']
y debería funcionar:
function slug_get_phone_number($post, $field_name, $request)
{
return get_post_meta($post['id'], '_phone', true);
}
Recomiendo cambiar _phone
por phone_number
u otra cosa sin el prefijo de guión bajo. Porque _
se usa frecuentemente con claves de metadatos privados. Intenta añadir un campo personalizado que tenga una clave de meta con prefijo _
directamente a tu post, y verás a lo que me refiero.

Simplemente añade estos métodos a function.php
add_action( 'rest_api_init', 'create_api_posts_meta_field' );
function create_api_posts_meta_field() {
// register_rest_field ( 'tipo-de-post', 'nombre-del-campo-a-retornar', array-de-callbacks-y-esquema() )
register_rest_field( 'tour', 'metaval', array(
'get_callback' => 'get_post_meta_for_api',
'schema' => null,
)
);
}
function get_post_meta_for_api( $object ) {
//obtiene el id del array del objeto post
$post_id = $object['id'];
//retorna el post meta
return get_post_meta( $post_id );
}

Aquí hay un ejemplo de POO (Programación Orientada a Objetos):
class MetaDataFetcher{
public function enableAPIroute(){
add_action ('rest_api_init', array($this, 'doRegisterRoutes'));
}
public function doRegisterRoutes(){
register_rest_route(
'yournamespace/vXX',
'fetch-post-meta',
array(
'methods' => array('GET','POST'),
'callback' => array($this, 'returnMetaData'),
//Deberías tener una mejor autenticación, o este endpoint estará expuesto
'permission_callback' => function(){return TRUE;}
)
);
}
public function returnMetaData(){
if (!(isset($_REQUEST['post-id']))){
return "ERROR: No hay ID de entrada";
}
$postID = $_REQUEST['post-id'];
$meta = get_post_meta($postID);
$meta = json_encode($meta);
return $meta;
}
}
$MetaDetaFetcher = New MetaDataFetcher;
$MetaDetaFetcher->enableAPIroute();

Probé y usé lo que me parece una forma más sencilla, después de registrar el tipo de entrada personalizado también puedes registrar los metadatos personalizados y hacerlos disponibles en la API REST.
Mira register_meta()
register_post_type( 'job_listing', $args ); // en $args puedes hacer que el tipo de entrada esté disponible en la API REST
register_meta(
'post', '_phone', [
'object_subtype' => 'job_listing',
'show_in_rest' => true
]
);
