WP Rest API: ¿detalles de la última publicación incluyendo URL de medios destacados en una sola solicitud?
Estoy usando la wp-rest api para obtener información de posts. También uso filtros de wp rest api para filtrar campos y resumir el resultado:
Cuando llamo a http://example.com/wp-json/wp/v2/posts?items=id,title,featured_media
devuelve resultados como este:
[
{
"id": 407,
"title": {
"rendered": "Título 1"
},
"featured_media": 399
},
{
"id": 403,
"title": {
"rendered": "Título 2"
},
"featured_media": 401
}
]
La pregunta es ¿cómo puedo generar la URL del medio destacado usando este ID? Por defecto, llamar a http://example.com/wp-json/wp/v2/media/401
devuelve un nuevo json que tiene todos los detalles sobre la URL de diferentes tamaños de la imagen fuente:
{
"id": 401,
"date": "2016-06-03T17:29:09",
"date_gmt": "2016-06-03T17:29:09",
"guid": {
"rendered": "http://example.com/wp-content/uploads/mi-nombre-imagen.png"
},
"modified": "2016-06-03T17:29:09",
"modified_gmt": "2016-06-03T17:29:09",
"slug": "mi-nombre-imagen",
"type": "attachment",
"link": "http://example.com/mi-url-post",
"title": {
"rendered": "mi-nombre-imagen"
},
"author": 1,
"comment_status": "open",
"ping_status": "closed",
"alt_text": "",
"caption": "",
"description": "",
"media_type": "image",
"mime_type": "image/png",
"media_details": {
"width": 550,
"height": 250,
"file": "mi-nombre-imagen.png",
"sizes": {
"thumbnail": {
"file": "mi-nombre-imagen-150x150.png",
"width": 150,
"height": 150,
"mime_type": "image/png",
"source_url": "http://example.com/wp-content/uploads/mi-nombre-imagen-150x150.png"
},
"medium": {
"file": "mi-nombre-imagen-300x136.png",
"width": 300,
"height": 136,
"mime_type": "image/png",
"source_url": "http://example.com/wp-content/uploads/mi-nombre-imagen-300x136.png"
},
"one-paze-port-thumb": {
"file": "mi-nombre-imagen-363x250.png",
"width": 363,
"height": 250,
"mime_type": "image/png",
"source_url": "http://example.com/wp-content/uploads/mi-nombre-imagen-363x250.png"
},
"one-paze-blog-thumb": {
"file": "mi-nombre-imagen-270x127.png",
"width": 270,
"height": 127,
"mime_type": "image/png",
"source_url": "http://example.com/wp-content/uploads/mi-nombre-imagen-270x127.png"
},
"one-paze-team-thumb": {
"file": "mi-nombre-imagen-175x175.png",
"width": 175,
"height": 175,
"mime_type": "image/png",
"source_url": "http://example.com/wp-content/uploads/mi-nombre-imagen-175x175.png"
},
"one-paze-testimonial-thumb": {
"file": "mi-nombre-imagen-79x79.png",
"width": 79,
"height": 79,
"mime_type": "image/png",
"source_url": "http://example.com/wp-content/uploads/mi-nombre-imagen-79x79.png"
},
"one-paze-blog-medium-image": {
"file": "mi-nombre-imagen-380x250.png",
"width": 380,
"height": 250,
"mime_type": "image/png",
"source_url": "http://example.com/wp-content/uploads/mi-nombre-imagen-380x250.png"
},
"full": {
"file": "mi-nombre-imagen.png",
"width": 550,
"height": 250,
"mime_type": "image/png",
"source_url": "http://example.com/wp-content/uploads/mi-nombre-imagen.png"
}
},
"image_meta": {
"aperture": "0",
"credit": "",
"camera": "",
"caption": "",
"created_timestamp": "0",
"copyright": "",
"focal_length": "0",
"iso": "0",
"shutter_speed": "0",
"title": "",
"orientation": "0",
"keywords": [ ]
}
},
"post": 284,
"source_url": "http://example.com/wp-content/uploads/mi-nombre-imagen.png",
"_links": {
"self": [
{
"href": "http://example.com/wp-json/wp/v2/media/401"
}
],
"collection": [
{
"href": "http://example.com/wp-json/wp/v2/media"
}
],
"about": [
{
"href": "http://example.com/wp-json/wp/v2/types/attachment"
}
],
"author": [
{
"embeddable": true,
"href": "http://example.com/wp-json/wp/v2/users/1"
}
],
"replies": [
{
"embeddable": true,
"href": "http://example.com/wp-json/wp/v2/comments?post=401"
}
]
}
}
Pero considera el caso cuando quiero obtener una lista de posts y sus miniaturas. Una vez debo llamar a http://example.com/wp-json/wp/v2/posts?items=id,title,featured_media
luego debo llamar a http://example.com/wp-json/wp/v2/media/id
10 veces para cada ID de medio y luego analizar los resultados y obtener la URL final de la miniatura del medio. Así que necesita 11 solicitudes para obtener detalles de 10 posts (una para la lista, 10 para miniaturas).
¿Es posible obtener estos resultados en una sola solicitud?
¡Ah, acabo de tener este problema yo mismo! Y aunque _embed
es genial, en mi experiencia es muy lento, y el punto de JSON es ser rápido :D
Tengo el siguiente código en un plugin (utilizado para agregar tipos de publicaciones personalizadas), pero imagino que podrías colocarlo en el archivo function.php
de tu tema.
php
add_action( 'rest_api_init', 'add_thumbnail_to_JSON' );
function add_thumbnail_to_JSON() {
//Agregar imagen destacada
register_rest_field(
'post', // Dónde agregar el campo (Aquí, publicaciones del blog. Podría ser un array)
'featured_image_src', // Nombre del nuevo campo (Puedes llamarlo como quieras)
array(
'get_callback' => 'get_image_src',
'update_callback' => null,
'schema' => null,
)
);
}
function get_image_src( $object, $field_name, $request ) {
$feat_img_array = wp_get_attachment_image_src(
$object['featured_media'], // ID de adjunto de la imagen
'thumbnail', // Tamaño. Ej. "thumbnail", "large", "full", etc.
true // Si la imagen debe tratarse como un icono.
);
return $feat_img_array[0];
}
Ahora en tu respuesta JSON deberías ver un nuevo campo llamado "featured_image_src":
que contiene una URL a la miniatura.
Lee más sobre cómo modificar respuestas aquí:
http://v2.wp-api.org/extending/modifying/
Y aquí hay más información sobre las funciones register_rest_field
y wp_get_attachment_image_src()
:
1.) https://developer.wordpress.org/reference/functions/register_rest_field/
2.) https://developer.wordpress.org/reference/functions/wp_get_attachment_image_src/
**Nota: ¡No olvides las etiquetas <?php ?>
si este es un nuevo archivo php!

Esto funciona genial y ayuda a que no sea necesario usar _embed ya que solo quiero la imagen destacada en tamaño completo. Tuve que cambiarlo a: ($object['featured_media'], 'fullsize', false);
para que no me diera la URL de la miniatura, pero funciona perfectamente a través de functions.php --¡Gracias!

Toda esta manipulación con el endpoint de la API REST me recuerda por qué me gusta GraphQL y que debería terminar los wrappers de la API REST y los nuevos resolvers personalizados ;-) De todos modos, es una solución inteligente y de hecho yo uso endpoints personalizados en producción para obtener los datos que necesito (y solo esos).

El nuevo plugin tiene http://mahditajik.ir/wp-json/wp/v2/media/<id>
pero contiene muchos datos extra que hacen lenta la respuesta, ¿cómo puedo personalizar la respuesta de la API REST?

¡Muchas gracias, me ayudó a completar mi función de contenido destacado! :D

Solo añade el argumento de consulta _embed
a tu URL solicitando los posts, y cada objeto de post incluirá el objeto _embedded.[wp:featuredmedia]
, que contiene todas las imágenes, al igual que el recurso /media/$id
. Si quieres un tamaño específico, accede a él por su nombre de propiedad, por ejemplo: _embedded[wp:featuredmedia][0].media_details.sizes.full.source_url
o para su miniatura: _embedded[wp:featuredmedia][0].media_details.sizes.thumbnail.source_url
Es decir, el objeto incrustado wp:featuredmedia incluye todas las URLs y detalles para cada tamaño disponible de tu post, pero si solo quieres la imagen destacada original, puedes usar el valor en esta clave: post._embedded["wp:featuredmedia"][0].source_url
Lo uso en un sitio con algo como esto (utiliza tu propio dominio, por supuesto):
$.get('https://example.com/wp-json/wp/v2/posts/?categories=3&_embed',
function(posts) {
var elems = '';
posts.forEach(function(post){
var link = post.link;
var title = post.title.rendered;
var pic = post._embedded["wp:featuredmedia"][0].source_url);
elems += '<div class="this_week"><a href="' + link + '" target="_blank">';
elems += '<img src="' + pic + '" title="' + title + '"/><span class="title">';
elems += title + '</span></a></div>';
});
$('#blockbusters').html(elems);
});
});
¿Ves? No necesitas dos consultas, solo añade _embed
como argumento de consulta, y entonces tendrás toda la información que necesitas para usar el mejor tamaño para tu vista.
