Formateo de Respuesta en Endpoint Personalizado de WP-API v2

18 ago 2016, 00:58:45
Vistas: 14.1K
Votos: 8

Estoy intentando usar un endpoint personalizado (básicamente para hacer funcionar un orden aleatorio) y estoy usando el siguiente código:

// Endpoint personalizado para WP API
function theme_enable_random_api() {

    // crear endpoint json-api

    add_action('rest_api_init', function () {

        // http://example.com/wp-json/random/v2/posts

        register_rest_route('random/v2', '/random', array (
            'methods'             => 'GET',
            'callback'            => 'wp_json_offers_v2__posts',
            'permission_callback' => function (WP_REST_Request $request) {
                return true;
            }
        ));
    });

    // manejar la solicitud

    function wp_json_offers_v2__posts($request) {
        // parámetros json-api

        $parameters = $request->get_query_params();

        // argumentos de búsqueda por defecto

        $args = array(
            'post_type'     => $parameters['type'],
            'numberposts'   => 9,
            'offset'        => $parameters['offset'],
            'post_not_in'       => $parameters['exclude'],
            'orderby'       => 'rand',
        );

        // ejecutar consulta

        $posts = get_posts($args);

        // devolver resultados
        return new WP_REST_Response($posts, 200);
    }

}

add_action('init', 'theme_enable_random_api');

Sin embargo, la respuesta que obtengo no es la misma que obtendría de una llamada estándar a la API.

Estándar:

Respuesta estándar de la API de WordPress

Endpoint Personalizado:

Respuesta de endpoint personalizado

El problema principal es que no puedo acceder a la información de taxonomías/campos ACF como lo hago en el endpoint estándar. No soy experto en PHP así que probablemente no lo estoy haciendo correctamente.

Saludos.

0
Todas las respuestas a la pregunta 3
3
10

Puedes llamar a los métodos de la API REST para preparar tu salida de la misma manera que lo hace el plugin por defecto, esto también permitirá que otros plugins se integren con la salida ya que has utilizado el plugin ACF como se ve en tu ejemplo de salida.

La clase WP_REST_Posts_Controller tiene lo siguiente en su método para obtener posts:

$posts_query = new WP_Query();
$query_result = $posts_query->query( $query_args );

$posts = array();
foreach ( $query_result as $post ) {
    if ( ! $this->check_read_permission( $post ) ) {
        continue;
    }

    $data = $this->prepare_item_for_response( $post, $request );
    $posts[] = $this->prepare_response_for_collection( $data );
}

Así que podrías instanciar un nuevo objeto WP_REST_Posts_Controller y llamar a los métodos prepare_item_for_response y prepare_response_for_collection en tus datos para formatearlos de manera idéntica a los endpoints por defecto.

Algo similar a lo siguiente debería funcionar (no probado):

function wp_json_offers_v2__posts($request) {
    // parámetros de json-api
    
    $parameters = $request->get_query_params();

    // argumentos de búsqueda por defecto
    
    $args = array(
        'post_type'     => $parameters['type'],
        'numberposts'   => 9,
        'offset'        => $parameters['offset'],
        'post_not_in'   => $parameters['exclude'],
        'orderby'       => 'rand',
    );

    // ejecutar consulta
    
    $posts = get_posts($args);

    $controller = new WP_REST_Posts_Controller($parameters['type']);

    foreach ( $posts as $post ) {
       $data    = $controller->prepare_item_for_response( $post, $request );
       $posts[] = $controller->prepare_response_for_collection( $data );
    }

    // devolver resultados
    return new WP_REST_Response($posts, 200);
}
18 ago 2016 12:51:21
Comentarios

Estoy experimentando un problema similar pero tu respuesta solo lo resuelve parcialmente, creo: Yo también tengo exactamente el mismo problema pero el mío resulta de un objeto WP Post que en realidad es una revisión. Intenté preparar el objeto post como lo hiciste tú, y también probé usando un controlador de revisiones. $latest_revision = wp_get_post_revisions( $id, $args ); $postController = new \WP_REST_Revisions_Controller('revision'); $response = $postController->prepare_item_for_response( $latest_revision, $request ); print_r($response);

Merc Merc
20 nov 2017 19:10:59

Pero estoy recibiendo muchos de estos: <b>Notice</b>: Trying to get property of non-object in <b>/Users/jones/Documents/github/lucid/sos-aerzte-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>350</b><br /> en diferentes líneas.`

Creo que se refieren a las líneas https://developer.wordpress.org/reference/classes/wp_rest_revisions_controller/ -> línea 350 > author

Merc Merc
20 nov 2017 19:14:45

Resolví el problema haciendo esto: https://stackoverflow.com/a/47402964/1121268 – No entiendo completamente por qué, pero con revisiones esto parece funcionar...

Merc Merc
21 nov 2017 01:43:30
0

La respuesta aceptada fue útil. Gracias. Pero el método prepare_item_for_response() quedó obsoleto desde la versión 3.0, así que espero que este fragmento de código ayude a alguien con un endpoint personalizado para pedidos de WC.

    // Parsear todos los demás parámetros
    $args = wp_parse_args( $request->get_params(), $args );

    // Obtener los pedidos
    $orders = wc_get_orders( $args );

    if ( ! empty( $orders ) && is_array( $orders ) ) {
        $controller = new WC_REST_Orders_Controller ();

        // Los datos de respuesta
        $orders_data = [];
        // Necesitamos preparar los objetos para la respuesta
        foreach ( $orders as $order ) {
            if ( $order instanceof WC_Order ) {
                // Objetos
                $prepared_object = $controller->prepare_object_for_response( $order, $request );
                $orders_data[]   = $controller->prepare_response_for_collection( $prepared_object );
            } else {
                // IDs
                $orders_data[] = (int) $order;
            }
        }

        // Retornar la respuesta
        return new WP_REST_Response( $orders_data, 200 );

    }
14 feb 2020 15:15:04
0

La respuesta anterior olvidó establecer una nueva variable de array. Una vez que agregas eso, funciona perfectamente.

function get_all_posts($request)
{
    $posts = get_posts([
        'posts_per_page' => -1,
        'post_status' => 'publish'
    ]);

    $controller = new WP_REST_Posts_Controller('post');

    $array = [];

    foreach ( $posts as $post ) {
        $data = $controller->prepare_item_for_response($post,$request);
        $array[] = $controller->prepare_response_for_collection($data);
    }

    return $array;
}

La salida se ve exactamente igual que la respuesta normal de la API.

28 mar 2018 17:26:44