#WCMontclair salcode.com

Fun with the WordPress REST API

Sal Ferrarello / @salcode

salferrarello.com/slides/wp-rest-api-fun

( Jump to Resources )

Ordering Sandwiches

JSON


  {
    "name": {
      "first": "Sal",
      "last": "Ferrarello"
    },
    "wcus": [
      2015, 2016
    ]
  }

https://salferrarello.com/wp-json/salcode/v1/owner

Why?

Blog Post Webpage
JSON response from WordPress REST API for blog post https://salferrarello.com/wp-json/wp/v2/posts/6799

Chrome Extension

Git of Chrome Extension retrieving when WordPress post was modified.

source code

Reading and Writing

Blog post with the title 'My example page'

Update title


await wp.apiFetch({
  data: {
    title: 'My new title',
  },
  method: 'POST',
  path: 'wp/v2/pages/8926'
});
Blog post with value updated to 'My new title'
Blog post with the title 'My example page' Blog post with value updated to 'My new title'

Big Ideas

  • Read from REST API
  • Write to REST API
  • Add new endpoints

JSON


  {
    "name": {
      "first": "Sal",
      "last": "Ferrarello"
    },
    "wcus": [
      2015, 2016
    ]
  }

https://salferrarello.com/wp-json/salcode/v1/owner
JSON PHP

 {
   "name": {
     "first": "Sal",
     "last": "Fe..."
   },
   "wcus": [
     2015, 2016
   ]
 }

 [
   'name' => [
     'first' => 'Sal',
     'last' => 'Fe...',
   ],
   'wcus' => [
     2015, 2016,
   ]
 ]

Unformatted JSON


  {"name":{"first":"Sal","last":
  "Ferrarello"},"wcus":[2015,2016]}







https://salferrarello.com/wp-json/salcode/v1/owner

Unformatted JSON


  {"name":{"first":"Sal","last":
  "Ferrarello"},"wcus":[2015,2016]}







https://salferrarello.com/wp-json/salcode/v1/owner

Formatted JSON


  {
    "name": {
      "first": "Sal",
      "last": "Ferrarello"
    },
    "wcus": [
      2015, 2016
    ]
  }
https://salferrarello.com/wp-json/salcode/v1/owner

JSONVue

Chrome browser extension to pretty print JSON

See JSONVue in Chrome Web store

source code

Formatting Alternative

While not as convenient as a browser extension, you can use this JS trick

await (await fetch(
  window.location.href
)).json()

See Pretty Print JSON URL blog post

Which URL?

How to find blog post REST API URL


<link
  rel="alternate"
  type="application/json"
  href="https://salferrarello.com/wp-json
    /wp/v2/posts/6799"
/>

source: https://salferrarello.com/math-metaphors/

URL to REST API endpoint for current blog post in link tag in markup.

https://salferrarello.com/wp-json/wp/v2/posts/6799

Find REST API URL with JavaScript


document.querySelector(
  'link[rel="alternate"]' +
  '[type="application/json"]'
).href

https://salferrarello.com/wp-json/wp/v2/posts/6799

Run JS in Browser Console

Query blog post DOM for REST API URL.

https://salferrarello.com/wp-json/wp/v2/posts/6799

JavaScript


(await (await fetch(
  '/wp-json/wp/v2/posts/6799'
)).json())
JavaScript fetching blog post data from REST API.

https://salferrarello.com/wp-json/wp/v2/posts/6799

Last Modified (JS)


jsonData = (await (await fetch(
  '/wp-json/wp/v2/posts/6799'
)).json());
jsonData.modified

https://salferrarello.com/wp-json/wp/v2/posts/6799

Chrome Extension

Git of Chrome Extension retrieving when WordPress post was modified.

source code

Same-origin Policy

Web browser JavaScript can only access URLs on the same domain

Same-origin policy

Exploring WP REST API

Single Post

https://salferrarello.com/wp-json/wp/v2/posts/6799

wp/v2 Routes

https://salferrarello.com/wp-json/wp/v2/

Structure

Base


https://example.com/wp-json/

Route (a.k.a. Path)


wp/v2/post/6799

Route

wp/v2/post/6799

First Part is "Namespace"

wp/v2

Route

salcode/v1/owner

Namespace

salcode/v1

Route

salcode-v1/owner

Namespace

salcode-v1

Route

salcodev1/owner

Namespace

salcodev1

Route

tuna/owner

Namespace

tuna

Route

salcode/v1/owner

Namespace

salcode/v1

No route was found

https://salferrarello.com/wp-json/wp/

Namespace

wp/v2

REST FORBIDDEN

WordPress REST API request returning REST Forbidden 401 /wp-json/wp-site-health/v1/tests/background-updates

REST Forbidden (JS)


(await (await fetch(
  '/wp-json/wp-site-health/v1/' +
  'tests/background-updates'
)).json());

REST Forbidden (JS)

JavaScript call to background-updates endpoint failing.

REST Authenticated (JS)


(await (await fetch(
  '/wp-json/wp-site-health/v1/' +
  'tests/background-updates'



)).json());

REST Authenticated (JS)


(await (await fetch(
  '/wp-json/wp-site-health/v1/' +
  'tests/background-updates',
  {
    headers: { 'X-Wp-Nonce': 'd2bd6ec6c3' },
  }
)).json());

REST with Nonce (JS)

JavaScript call to background-updates endpoint suceeding when we include the X-Wp-Nonce.

X-Wp-Nonce

On /wp-admin pages available from JavaScript global

wpApiSettings.nonce

Also available at the URL

/wp-admin/admin-ajax.php?action=rest-nonce

wp.apiFetch()

await wp.apiFetch({
  path: '/wp-site-health/v1/' +
    'tests/background-updates'
})

wp.apiFetch()

JavaScript call to background-updates endpoint suceeding when we use wp.apiFetch().

Update title


await wp.apiFetch({
  data: {
    title: 'My new title',
  },
  method: 'POST',
  path: 'wp/v2/pages/8926'
});
Read Write
await wp.apiFetch({
  path:
    'wp/v2/pages/9'
});





await wp.apiFetch({
  path:
    'wp/v2/pages/9',

  method: 'POST',
  data: {
    title: 'New title',
  },
});

Route vs Endpoint

An office full of desks with people sitting at them.

Routes vs Endpoints

Adding a REST API Endpoint


add_action(
  'rest_api_init',
  'salcode_owner_rest'
);

https://github.com/salcode/owner-rest-endpoint

function salcode_owner_rest() {
  register_rest_route(
    'salcode/v1', '/name',
    [
      'callback' => 'salcode_owner_callback',
      'permission_callback' =>
                            '__return_true',
    ]
  );
}
https://github.com/salcode/owner-rest-endpoint

function salcode_owner_callback() {
  return [
    'name' =>
      [
        'first' => 'Sal',
        'last' => 'Ferrarello'
      ],
    'wcus' => [ 2015, 2016 ],
  ];
}
https://github.com/salcode/owner-rest-endpoint

Result


  {
    "name": {
      "first": "Sal",
      "last": "Ferrarello"
    },
    "wcus": [
      2015, 2016
    ]
  }

https://salferrarello.com/wp-json/salcode/v1/owner

Remember REST FORBIDDEN


register_rest_route(
  'salcode/v1', '/name',
  [
    'callback' => 'salcode_owner_callback',
    'permission_callback' =>
                          '__return_true',
  ]
);

Where Do I Put This Code?

  • functions.php
  • a custom plugin you write
  • mu-plugins directory

mu-plugins ?

/wp-content/mu-plugins/

Example

/wp-content/mu-plugins/owner-rest-endpoint.php

Same-origin Policy

MyWeather Plugin adds REST endpoint with weather

https://ferrarello.com/wp-json/myweather/v1/weather

https://ferrarello.com/weather/

Resources

WebDevStudios

Sal Ferrarello

salcode.com/wcm

Image Credits