Formateo de Respuesta en Endpoint Personalizado de WP-API v2
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:
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.
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);
}

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);

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

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

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 );
}

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.
