【WordPress】WordPressの投稿一覧を他サイトで表示する【WP REST API】後編

WPRESTAPI

前編はAPIとは何か、RESTとは何かを説明しました。
もしご覧になりたい方は以下からお願いします。

WPRESTAPI 【WordPress】WordPressの投稿一覧を他サイトで表示する【WP REST API】前編

wp-json

前編でも紹介した通り、WordPressにはバージョン4.7.xから標準でWP REST APIというものが組み込まれています。

ご自身のWordPressのURIの最後に/wp-jsonを追記してアクセスしてみてください。
何やら複雑な文字列が表示されたかと思います。
この文字列はJSONと呼ばれるデータフォーマットで、JavaScript Object Notationの略です。
JavaScriptのオブジェクトの記法なので、JavaScriptを知っている方なら馴染みがあるかと思います。

つまり、

https://ブログのアドレス/wp-json

となります。
このURIではどのルートが使えるか、どのエンドポイントがそれぞれのルートで使えるかをJSON形式で返してくれています。こちらが大元となり、これに欲しいリソースの分URIを付け足していきます。

今回は投稿一覧を取得するというのが目的です。リファレンスを見てみましょう。

Postを取得する→リクエスト例ではhttp://demo.wp-api.org/wp-json/wp/v2/postsとなっております。
つまり、

https://ブログのアドレス/wp-json/wp/v2/posts

にアクセスすると投稿一覧がJSON形式で返ってきます。

こちらを元に実際にJavaScriptを用いてWebページにリソースを出力する処理をしてみます。

fetchメソッド

fetchメソッドを使います。
fetchメソッドの説明は詳しくは行いませんのでご了承ください。
リファレンスがとてもわかりやすいので以下からのぞいてみてください。

実際にやってみる

index.htmlscript.jsを用意して、以下のコードでindex.htmlを開いてください。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="script.js"></script>
</head>
<body>
  
</body>
</html>

fetch()の引数は各自のURIに変更してください。

'use strict';

const main = () => {
  fetch('https://ブログのアドレス/wp-json/wp/v2/posts')
  .then(response => response.json())
  .then(data => console.log(data));
}

window.addEventListener('DOMContentLoaded', main);

※ブラウザはChromeです。
真っ白のページで、右クリック→検証→Consoleとしてください。

▶︎を押すと展開されます。
更に▶︎0を展開するとズラッと文字が並びます。
これらが投稿した記事の詳細な情報です。

この中から今回は投稿タイトル、投稿日時、アイキャッチ画像、記事のアドレスを取得してみます。
また、表示する記事の上限を3に設定してみます。

それぞれを取り出してみる

アイキャッチ画像はこのままでは取り出せないので、URIを以下にします。

https://ブログのアドレス/wp-json/wp/v2/posts?_embed

また、記事の表示上限を設ける場合は更に以下にします。今回は最新の3件を表示にします。

https://ブログのアドレス/wp-json/wp/v2/posts?_embed&per_page=3

上記のような取得したい条件がある場合にはパラメータを指定する必要があります。
英語サイトですが、WP REST APIのハンドブックを参考にするか、検索サイトで調べると出てくると思います。

これで先ほどのscript.jsにあるfetchメソッドを変更して、投稿タイトル、投稿日時、アイキャッチ画像、記事のアドレスを取得していきます。
index.htmlも以下に変更します。style.cssも作成し、内容を入力します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css"><!-- 追記 -->
  <script src="script.js"></script>
</head>
<body>
  <div class="main"></div><!-- 追記 -->
</body>
</html>
const main = () => {
  (() => {
    let divParent = document.querySelector('.main');
    fetch('https://ブログのアドレス/wp-json/wp/v2/posts?_embed&per_page=3')
    .then((response) => { 
      if(response.ok) {
        return response.json();
      }
      throw new Error(`リクエスト失敗: ${response.status}`);})
    .then((data) => {
      data.forEach(item => {
        if(!item.featured_media) {
          item._embedded["wp:featuredmedia"] = [{source_url : 'images/noimage.gif'}];
        }

        const date = new Date(item.date);
        const yy = date.getFullYear();
        const mm = date.getMonth() + 1;
        const dd = date.getDate();

        let html = `<div class="item1"><a href="${item.link}" target="_blank" rel="noopener noreferrer"><img src="${item._embedded['wp:featuredmedia'][0].source_url}" class="topsam"></div><div class="item2">${yy}/${mm}/${dd}<br>${item.title.rendered}</div></a><hr>`;
        divParent.innerHTML += html;
        });
      })
    .catch( (e) => {
      divParent.innerHTML += '<br>記事がありません。';
      console.log(e.message);
    });
  })();
}
window.addEventListener('DOMContentLoaded', main);
.topsam {
  width: 150px;
  height: auto;
}

解説

それでは1つずつ説明をしていきます。
index.htmlにはcssファイルとjsファイルを読み込む記述と、divタグ、こちらにmainというクラスをつけています。

style.cssはアイキャッチ画像のサイズを設定しています。

さて肝心のscript.jsです。
use strictは変数宣言しないと使えなくする厳格モードに入るお決まりフレーズ、DOMContentLoadedはhtmlのheadタグ内で読み込まれてもDOMツリー構築後に実行されるので基本的に記入しておきます。

main関数の中身、先ほどindex.html内で記入したdivタグを変数divParentに格納します。

fetchメソッドですが、返り値にPromiseというオブジェクトが返ってきます。

fetch() はプロミスを返し、これはこのリソースフェッチ捜査に関連付けられた Response オブジェクトで解決します。

https://developer.mozilla.org/ja/docs/Web/API/Response

なんのこっちゃですが、このPromiseはResponseオブジェクトも取得できると考えた方がいいかと思われます。
Responseオブジェクトはリクエストを送って、返ってくるHTTPレスポンス全体を取得していますので、ここではまだJSONの本文は取得できません。

ここから更にjsonメソッドを使用します。

Response オブジェクトから JSON の本文の内容を抽出するには、 json() メソッドを使用します。これはレスポンス本文のテキストを JSON として解釈した結果で解決する第 2 のプロミスを返します。

https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch

返ってきたresponseにresponse.json()をreturnし、更にthenを繋ぐとJSONとして解釈したPromiseが返ってきます。
ここからHTMLに表示する処理を行います。

と、その前にif文を使っている箇所があります。条件はresponse.okというResponseオブジェクトのプロパティ。

fetch() から返されるプロミス (Promise) は、レスポンスが HTTP 404 や 500 を返す HTTP エラーステータスの場合でも拒否されません。サーバーがヘッダーで応答すると、プロミスは直ちに正常に解決します(レスポンスが 200-299 の範囲にない場合は、レスポンスの ok (en-US) プロパティが false に設定されます)。

https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch

200番台は成功レスポンスですので、response.okがtrueの時のみ先ほどのresponse.json()を返すようにし、falseつまりエラーレスポンスの時はエラーを投げてcatchでコンソールにエラー内容を表示する処理をさせています。
エラーになると何も表示されないので、記事がありませんと表示させるようにしています。

trueの場合はJSONとして解釈したPromiseが返ります。何が返ってきているかわかりやすくするためにthenメソッドの先頭にconsole.log(data)と指定してあげると何が返ってきてるかわかりますね。

index.htmlを開いた状態で右クリック→検証→Consoleとしてください。

※ブラウザはChromeです。

何が返ってきているかというと配列が返ってきています。その中にオブジェクトが格納されています。パラメータで最新3件取得としたので、3件が返ってきています。
これらを1つずつ取り出して、必要な情報を取得しHTMLに書き出していきます。

そこで、forEachメソッドを使用して1つずつ取り出していきましょう。

アイキャッチ画像は_embedded[‘wp:featuredmedia’][0].source_urlで取得できるのですが、アイキャッチ画像を設定していないとこのオブジェクト自体ないのでエラーとなってしまいます。
なので、それを回避するためにif判定をしておき、アイキャッチ画像を設定していなければnoimageというような画像が表示されるようにしています。
なので、imagesディレクトリを作り、適当な画像を用意しておいてください(サイズはCSSで変更されるのでなんでも可)。

次ですが、日時を取得したい場合です。
そのままだとISO8601のフォーマットyyyy-MM-ddTHH:mm:ssで表示されています。
分割もできませんので、Dateオブジェクトを生成して扱いやすくします。

Dateを扱いやすくそれぞれ変数に格納し、その後はhtmlへ吐き出す処理をしています。
それぞれ何が取得できる変数か下記に記します。

投稿日時(ISO8601)date
記事のアドレスlink
記事のタイトルtitle.rendered
アイキャッチ画像_embedded[‘wp:featuredmedia’][0].source_url

どうだったでしょうか。
他にも記事の内容を取得する方法や、投稿者ごと、カテゴリーごとにわけて取得したりと幅広くできます。

ただ、WP REST APIはセキュリティ的に問題があるので、セキュリティを高める記事を投稿予定です。