Dev

Add Featured Images to the WordPress API

Can I get a url please?

I’ve been working with the WordPress API lately, and while it’s certainly better than admin-ajax, it still has a way to go. But, there’s enough there to begin integrating more JavaScript-based / headless CMS solutions.

However, one troublesome issue I’ve encountered is the lack of support for Featured Images out the gate.

Take the standard post endpoint for

GET /wp-json/wp/v2/posts

All you get back for Featured Media is its id and another endpoint reference for additional info.


[
  "featured_media": 68,
  "_links": {
    "wp:featuredmedia": [
      {
        "embeddable": true,
        "href": "http:\/\/stephenscaff.com\/wp-json\/wp\/v2\/media\/68"
      }
    ],
  }
]

Can I get the url?

Not wanting to make an additional request for each image, wouldn’t it be nice to have direct access to the Featured Image url within a single endpoint?

Well, there are 2 ways to do that – by appending _embed at the end of our request, or by modifying the endpoint response via register_rest_field hook.

1. _embed

By simply appending ?_embed to our request:

GET /wp-json/wp/v2/posts?_embed

we now return an _embedded node, containing a ton of stuff relating to the post’s Featured Image, including urls for the various available sizes.


[
  "wp:featuredmedia": [
    {
      "id": 453,
      "alt_text": "Hey Hey Hey",
      "media_details": {
        "width": 2000,
        "height": 1200,
        "file": "2017/07/post-nested.jpg",
        "sizes": {
          "medium": {
          "file": "post-nested-1250x750.jpg",
          "width": 1250,
          "height": 750,
          "mime_type": "image/jpeg",
          "source_url": "http://stephenscaff.com/wp-content/uploads/2017/07/post-nested-1250x750.jpg"
        }
        ...
      }
    } 
  }
]

Cool. We can work with that. But, what if you just need the image url (and would rather avoid all that nesting)?

2. register_rest_field

As it turns out, WP has a handy function called register_rest_field that “registers a new field on an existing WordPress object.”

It accepts 3 params, $object type, $attribute, and $args (get_callback, update_callback, schema).

For our purposes, these params would consist of:

  • $object type – our target endpoint (ie: ‘post’, ‘custom post type name’, etc).
  • $attribute – ‘featured_image’
  • array(‘get_callback’) – Callback function that gets a post’s Featured Image.

Here’s simple class to add Featured Images to our posts endpoints, in addition to a custom post type called ‘product’.


 /**
  *  WpApiFeaturedImage
  *
  *  Adds featured images to the products endpoint
  *  using register_rest_field hook.
  *
  *  @version   1.0
  *  @author    stephen scaff
  */

 class WpApiFeaturedImage {

   /**
    * The endpoints we want to target
    */
   public $target_endpoints = '';

   /**
    * Constructor
    * @uses rest_api_init
    */
   function __construct() {
     $this->target_endpoints = array('product', 'post');
     add_action( 'rest_api_init', array( $this, 'add_image' ));
   }


   /**
    * Add Images to json api
    */
   function add_image() {

     /**
      * Add 'featured_image'
      */
     register_rest_field( $this->target_endpoints, 'featured_image',
        array(
          'get_callback'    => array( $this, 'get_image_url_full'),
          'update_callback' => null,
          'schema'          => null,
        )
      );

      /**
       * Add 'featured_image_thumbnail'
       */
      register_rest_field( $this->target_endpoints, 'featured_image_thumbnail',
         array(
           'get_callback'    => array( $this, 'get_image_url_thumb'),
           'update_callback' => null,
           'schema'          => null,
         )
       );
    }

  /**
   * Get Image: Thumb
   */
  function get_image_url_thumb(){
    $url = $this->get_image('thumbnail');
    return $url;
  }

  /**
   * Get Image: Full
   */
  function get_image_url_full(){
    $url = $this->get_image('full');
    return $url;
  }

  /**
   * Get Image Helpers
   */
  function get_image($size) {
    $id = get_the_ID();

    if ( has_post_thumbnail( $id ) ){
        $img_arr = wp_get_attachment_image_src( get_post_thumbnail_id( $id ), $size );
        $url = $img_arr[0];
        return $url;
    } else {
        return false;
    }
  }
}

new WpApiFeaturedImage;

This class will edit our response to now include the direct urls for featured_image and featured_image_thumbnail. Fairly painless yeah?

Note the helper method get_image($size) for adding additional sizes. A smarter play might be to create a featured_image node, and nest the sizes within. But this worked best for my purposes at the time.

Feel free to snag the code from Github

Read Next

S+P Snags Some Love

Read Story