10

I'm using wp-rest api to get posts information. I also use wp rest api filter items to filter fields and summarize the result:

When I call http://example.com/wp-json/wp/v2/posts?items=id,title,featured_media it returns results like this:

[

    {
        "id": 407,
        "title": {
            "rendered": "Title 1"
        },
        "featured_media": 399
    },
    {
        "id": 403,
        "title": {
            "rendered": "Title 2"
        },
        "featured_media": 401
    }

]

The question is how can I generate featured media url using this id? By default calling http://example.com/wp-json/wp/v2/media/401 returns a new json which have all details about url of different sizes of source image:

{

    "id": 401,
    "date": "2016-06-03T17:29:09",
    "date_gmt": "2016-06-03T17:29:09",
    "guid": {
        "rendered": "http://example.com/wp-content/uploads/my-image-name.png"
    },
    "modified": "2016-06-03T17:29:09",
    "modified_gmt": "2016-06-03T17:29:09",
    "slug": "my-image-name",
    "type": "attachment",
    "link": "http://example.com/my-post-url",
    "title": {
        "rendered": "my-image-name"
    },
    "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": "my-image-name.png",
        "sizes": {
            "thumbnail": {
                "file": "my-image-name-150x150.png",
                "width": 150,
                "height": 150,
                "mime_type": "image/png",
                "source_url": "http://example.com/wp-content/uploads/my-image-name-150x150.png"
            },
            "medium": {
                "file": "my-image-name-300x136.png",
                "width": 300,
                "height": 136,
                "mime_type": "image/png",
                "source_url": "http://example.com/wp-content/uploads/my-image-name-300x136.png"
            },
            "one-paze-port-thumb": {
                "file": "my-image-name-363x250.png",
                "width": 363,
                "height": 250,
                "mime_type": "image/png",
                "source_url": "http://example.com/wp-content/uploads/my-image-name-363x250.png"
            },
            "one-paze-blog-thumb": {
                "file": "my-image-name-270x127.png",
                "width": 270,
                "height": 127,
                "mime_type": "image/png",
                "source_url": "http://example.com/wp-content/uploads/my-image-name-270x127.png"
            },
            "one-paze-team-thumb": {
                "file": "my-image-name-175x175.png",
                "width": 175,
                "height": 175,
                "mime_type": "image/png",
                "source_url": "http://example.com/wp-content/uploads/my-image-name-175x175.png"
            },
            "one-paze-testimonial-thumb": {
                "file": "my-image-name-79x79.png",
                "width": 79,
                "height": 79,
                "mime_type": "image/png",
                "source_url": "http://example.com/wp-content/uploads/my-image-name-79x79.png"
            },
            "one-paze-blog-medium-image": {
                "file": "my-image-name-380x250.png",
                "width": 380,
                "height": 250,
                "mime_type": "image/png",
                "source_url": "http://example.com/wp-content/uploads/my-image-name-380x250.png"
            },
            "full": {
                "file": "my-image-name.png",
                "width": 550,
                "height": 250,
                "mime_type": "image/png",
                "source_url": "http://example.com/wp-content/uploads/my-image-name.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/my-image-name.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"
            }
        ]
    }

}

But consider the case when I want to get list of posts and their thumbnails. One time I should call http://example.com/wp-json/wp/v2/posts?items=id,title,featured_media then I should call http://example.com/wp-json/wp/v2/media/id 10 times for each media id and then parse the results and get final url of media thumbnail. So it needs 11 request for get details of 10 post (one for list,10 for thumbnails). Is it possible to get this results in one request?

  • 1
    Did you registrer a new field for your response with register_rest_field ? – Benoti Oct 2 '16 at 14:34
  • @Benoti I will check its documentation. If there was more things to ask I will come back to you :) – VSB Oct 2 '16 at 16:44
  • It is right, you haven't the image date in the post request, only the ID of the featured media and a new request is necessary on the default of the WP API. – bueltge Oct 3 '16 at 9:18
  • If you add the _embed parameter, the post object returned includes all details about the featured media and all its sizes available. Check my response for an example. – Jesús Franco Oct 3 '16 at 20:53
13

Ah I just had this problem myself! And while _embed is great, in my experience it is very slow, and the point of JSON is to be fast :D

I have the following code in a plugin (used for adding custom post types), but I imagine you could put it in your theme's function.php file.

php

add_action( 'rest_api_init', 'add_thumbnail_to_JSON' );
function add_thumbnail_to_JSON() {
//Add featured image
register_rest_field( 
    'post', // Where to add the field (Here, blog posts. Could be an array)
    'featured_image_src', // Name of new field (You can call this anything)
    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'], // Image attachment ID
    'thumbnail',  // Size.  Ex. "thumbnail", "large", "full", etc..
    true // Whether the image should be treated as an icon.
  );
  return $feat_img_array[0];
}

Now in your JSON response you should see a new field called "featured_image_src": containing a url to the thumbnail.

Read more about modifying responses here:
http://v2.wp-api.org/extending/modifying/

And here's more information on theregister_rest_field and wp_get_attachment_image_src() functions:
1.) https://developer.wordpress.org/reference/functions/register_rest_field/
2.) https://developer.wordpress.org/reference/functions/wp_get_attachment_image_src/

**Note: Don't forget <?php ?> tags if this is a new php file!

  • 2
    This works great and helps that _embed does not need to be used since I only want the fullsize featured image. I did have to change it to: ($object['featured_media'], 'fullsize', false); to not give me the thumbnail url, but works perfectly via functions.php --Thanks! – Jordan Dec 4 '17 at 0:41
  • 1
    All of this juggling with the RES API endpoint reminds me why I like GraphQL and that I should finish the wrappers of REST API and new custom resolvers ;-) Anyway, it's a clever solution and actually I use custom endpoints in production to get the data I need (and just that). – Jesús Franco Dec 4 '17 at 16:20
  • New plugin have http://mahditajik.ir/wp-json/wp/v2/media/<id> but it has many extra data that make response slow so how I can customize REST api respond dto? – Kenji Apr 11 '18 at 15:19
  • Thanks a lot, it helped me to finish my featured content feature ! :D – Atem18 Jun 27 '18 at 17:17
  • 1
    I just wanted to let you know that this cut 2s out of my loading time! Thank you so much and for your carefully curated bibliography! – GuiHarrison Feb 12 at 19:53
6

Just add the _embed query argument to your URL asking for the posts, and every post object, will include the _embedded.[wp:featuredmedia] object, which includes all the images, just like the /media/$id resource. If you want an specific size, just access it by its property name, i.e.: _embedded[wp:featuredmedia][0].media_details.sizes.full.source_url or for its thumbnail: _embedded[wp:featuredmedia][0].media_details.sizes.thumbnail.source_url

That is, the wp:featuredmedia embedded object includes all the URLs and details for every size available for your post, but if you want just the original featured image, you can use the value in this key: post._embedded["wp:featuredmedia"][0].source_url

I use it in a site with something like this (use your own domain, of course):

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

See? No need for two queries, just add _embed as a query argument, and then you have all the information you need to use the best size for your view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.