Cómo actualizar/insertar datos de campos personalizados (post meta) con la API REST de WordPress
Estoy intentando agregar datos personalizados de posts (metadatos) a través de la API de WordPress pero estoy teniendo dificultades al actualizar/agregar estos datos personalizados. A continuación está el código que estoy usando.
Código escrito en functions.php
add_action( 'rest_api_init', 'create_api_posts_meta_field' );
function create_api_posts_meta_field() {
// register_rest_field ( 'nombre-del-tipo-de-post', 'nombre-del-campo-a-retornar', array-de-callbacks-y-esquema() )
register_rest_field( 'experience', 'subtitle', array(
'get_callback' => 'get_post_meta_for_api',
'update_callback' => 'update_post_meta_for_exp',
'schema' => null,
)
);
}
function update_post_meta_for_exp($object, $meta_value ) {
$havemetafield = get_post_meta($object['id'], 'experience', false);
if ($havemetafield) {
$ret = update_post_meta($object['id'], 'subtitle', $meta_value );
return true;
} else {
$ret = add_post_meta( $object['id'], 'subtitle', $meta_value ,true );
return true;
}
}
function get_post_meta_for_api( $object ) {
//obtener el id del array del objeto post
$post_id = $object['id'];
//retornar el post meta
return get_post_meta( $post_id )["Subtitle"][0];
}
function create_api_posts_meta_field_time() {
// register_rest_field ( 'nombre-del-tipo-de-post', 'nombre-del-campo-a-retornar', array-de-callbacks-y-esquema() )
register_rest_field( 'experience', 'timing_of_experience', array(
'get_callback' => 'get_post_meta_for_api_time',
'update_callback' => function($meta_value ) {
$havemetafield = get_post_meta(1, 'experience', false);
if ($havemetafield) {
$ret = update_post_meta(1, 'timing_of_experience', $meta_value );
return true;
} else {
$ret = add_post_meta( 1, 'timing_of_experience', $meta_value ,true );
return true;
}
},
'schema' => null,
)
);
}
function get_post_meta_for_api_time( $object ) {
//obtener el id del array del objeto post
$post_id = $object['id'];
//retornar el post meta
return get_post_meta( $post_id )["timing_of_experience"][0];
}
Archivo JS incluido en la página en la que estoy trabajando
var quickAddExperience = document.querySelector("#quick-add-experience");
if (quickAddExperience) {
quickAddExperience.addEventListener("click",function() {
var ourPostData = {
'title' : document.getElementById('title').value,
'content' : document.getElementById('content').value,
'subtitle' : document.getElementById('company_name').value,
'timing_of_experience' : document.getElementById('time_period').value,
'status' : 'publish'
}
console.log(ourPostData);
var createPost = new XMLHttpRequest();
createPost.open("POST", magicalData.siteURL + "/wp-json/wp/v2/experience-api");
createPost.setRequestHeader("X-WP-Nonce", magicalData.nonce);
createPost.setRequestHeader("Content-Type","application/json;charset=UTF-8");
createPost.send(JSON.stringify(ourPostData));
createPost.onreadystatechange = function(){
if (createPost.readystate == 4) {
if (createPost.status == 201) {
document.querySelector('.data-api-post-1 [name="title"]').value ='';
document.querySelector('.data-api-post-1 [name="content"]').value ='';
document.querySelector('.data-api-post-1 [name="company_name"]').value ='';
document.querySelector('.data-api-post-1 [name="time_period"]').value ='';
}else{
alert("Error - intenta nuevamente");
}
}
}
});
}
Este código funciona para los campos por defecto, es decir, se crea un nuevo post pero solo con el título y el contenido.
Edición: Cuando intenté depurar el código, me di cuenta de que el código update_callback no se está ejecutando pero get_callback sí se ejecuta.

Acabo de realizar una prueba con tu código y en mi opinión, no está funcionando porque tienes un error en la función get_callback
.
La primera vez intentará obtener el subtitle
(o el timing_of_experience
), pero generará un error porque no existe inicialmente, y este error bloqueará el registro del update_callback
.
Entonces, el problema es que en el get_callback
la clave Subtitle
tiene una S
mayúscula, y no es así como se guarda.
En segundo lugar, deberías respetar la regla general de validación de datos y verificar si el valor existe antes de intentar acceder a él. Así:
function get_post_meta_for_api( $object ) {
// Obtener el ID del array de objetos del post
$post_id = $object['id'];
$meta = get_post_meta( $post_id );
if ( isset( $meta['subtitle' ] ) && isset( $meta['subtitle' ][0] ) ) {
// Retornar el meta del post
return $meta['subtitle' ][0];
}
// Meta no encontrado
return false;
}
Como dije, realicé una prueba, reemplazando tu tipo de post experience
con post
y está funcionando.
Un consejo adicional, deberías intentar organizar mejor tu código, ya que es difícil de leer con esta indentación y orden de funciones. Además, para el update_callback
, un simple return true
es suficiente.
function update_post_meta_for_exp($object, $meta_value ) {
$havemetafield = get_post_meta($object['id'], 'experience', false);
if ($havemetafield) {
$ret = update_post_meta($object['id'], 'subtitle', $meta_value );
} else {
$ret = add_post_meta( $object['id'], 'subtitle', $meta_value ,true );
}
return true;
}

Puedes escribir datos personalizados de publicaciones usando el siguiente código. Yo escribí categorías de tipo de publicación personalizada "ad_portfolio" e imagen destacada en la API de WordPress usando el código de abajo. Espero que te ayude. Gracias
function preparar_rest($data, $post, $request){
$_data = $data->data;
$thumbnail_id = get_post_thumbnail_id( $post->ID );
$featured_media_url = wp_get_attachment_image_src( $thumbnail_id, 'large' );
$post_categories = wp_get_post_terms( $post->ID, 'ad_portfolios' , array("fields" => "all") );
$cats = array();
foreach($post_categories as $cat){
$cats[] = ['slug' => $cat->slug, 'name' => $cat->name ];
}
$_data['featured_media_url'] = $featured_media_url[0];
$_data['portfolio_cats'] = $cats;
$data->data = $_data;
return $data;
}
add_filter('rest_prepare_ad_portfolio', 'preparar_rest', 10, 3);
//el tipo de publicación es "ad_portfolio"
