Cómo actualizar/insertar datos de campos personalizados (post meta) con la API REST de WordPress

11 ene 2018, 08:10:31
Vistas: 18.1K
Votos: 4

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.

4
Comentarios

¿En qué parte no estás recuperando los valores? El mínimo de depuración es mostrar el contenido de las variables que no contienen el valor esperado.

mmm mmm
11 ene 2018 20:31:43

Lo siento, no entiendo lo que estás preguntando

Varun Naharia Varun Naharia
12 ene 2018 04:50:03

¿Puedes reducirlo a lo mínimo indispensable para reproducir el problema? Hay mucho código adicional que dificulta la lectura.

janh janh
15 ene 2018 16:49:00

@janh es el código mínimo.

Varun Naharia Varun Naharia
16 ene 2018 06:58:59
Todas las respuestas a la pregunta 2
0

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;
}
20 ene 2018 18:00:01
1

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"
16 ene 2018 19:28:01
Comentarios

Gracias por responder, pero no parece la solución que pedí. ¿Podrías explicar cómo funcionaría y por qué mi código no está funcionando?

Varun Naharia Varun Naharia
17 ene 2018 07:04:36