コンテンツへスキップ

WordPressのREST API基礎 — /wp-json/ で何ができるか

WordPressの管理画面やテーマは、実は裏側でHTTPのAPIを経由して動いている部分がある。投稿一覧をJavaScriptで動的に読み込んだり、外部のPHPスクリプトから「最新記事3件のタイトルと抜粋だけ」を取ってきたりする処理は、データベースに直接SQLを投げるのではなく、WordPress標準搭載のREST APIを叩くことで実現できる。この仕組みを知っていると、「別のシステムからWordPressの中身を覗きたい」という場面で、プラグインを追加したり管理画面をスクレイピングしたりせずに済む。

補足: REST(Representational State Transfer)とは、URLでリソース(投稿・固定ページ・ユーザーなど)を指定し、HTTPメソッド(GET/POST/PUT/DELETE)でそのリソースへの操作を表現するAPI設計のスタイル。WordPressのREST APIは、この考え方に沿って投稿やページ等をJSON形式でやり取りできるようにしたものである。

/wp-json/ は何をしているのか

WordPress 4.7(2016年)以降、標準インストールには最初からREST APIが組み込まれている。プラグイン不要で、サイトのURLに /wp-json/ を付けてブラウザでアクセスするだけで、そのサイトが公開しているAPIエンドポイント一覧がJSONで返ってくる。

投稿一覧を取得する代表的なエンドポイントは /wp-json/wp/v2/posts である。これにブラウザやcurlでアクセスすると、公開済み投稿がJSON配列として返る。各要素には投稿ID・タイトル(title.rendered)・本文(content.rendered)・抜粋(excerpt.rendered)・公開日時(date)・パーマリンク(link)などが含まれている。

GET https://example.com/wp-json/wp/v2/posts?per_page=3

per_page のようにURLのクエリパラメータで件数やページ番号、カテゴリでの絞り込みなどを指定できる。認証情報なしでアクセスできるのは、この posts エンドポイントが「公開済み投稿を読む」という、誰でも見られる情報を扱っているからである。逆に下書きの取得や、投稿の作成・更新・削除といった書き込み系の操作には認証が必要になる(詳細は後述)。

_embed パラメータで関連データをまとめて取る

素のレスポンスには、アイキャッチ画像やカテゴリ名そのものは含まれず、代わりにIDへの参照(featured_media の数値ID、categories の数値ID配列)だけが入っている。画像URLやカテゴリ名の文字列が欲しければ、本来はそれぞれ別のエンドポイント(/wp-json/wp/v2/media/<ID>/wp-json/wp/v2/categories/<ID>)に追加でアクセスして解決する必要がある。

これを1回のリクエストで済ませるのが _embed パラメータである。

GET /wp-json/wp/v2/posts?per_page=3&_embed

_embed を付けると、レスポンスの _embedded フィールドの中に、アイキャッチ画像の実データ(wp:featuredmedia)やタクソノミー項目(wp:term)がまとめて埋め込まれた状態で返ってくる。追加のリクエストを何度も発行せずに、投稿本体と関連データを1往復で取得できる。N+1問題(一覧の件数だけ追加リクエストが発生してしまう問題)を避ける定石として、REST APIを扱う場面ではまず押さえておきたい仕組みである。

実例: LPの「最新の記事」セクションをREST API経由で表示する

server/wpmm-web/includes/blog_latest.phpwpmm_fetch_latest_posts() は、この仕組みをそのまま利用している。JP/EN それぞれのランディングページ(LP)にある「最新の記事」セクションは、LP自身が持つデータベースを直接読むのではなく、ブログ側WordPressの /blog/wp-json/wp/v2/posts?per_page=3&_embed&status=publish にHTTPリクエストを投げて結果を組み立てている。

$api_url = ($lang === 'en')
    ? "https://en.wpmm.jp/blog/wp-json/wp/v2/posts?per_page={$count}&_embed&status=publish"
    : "https://wpmm.jp/blog/wp-json/wp/v2/posts?per_page={$count}&_embed&status=publish";

取得したJSONから、タイトル(title.rendered)・抜粋(excerpt.rendered)・パーマリンク(link)・アイキャッチ画像URL(_embedded['wp:featuredmedia'][0]['source_url'])・カテゴリ名(_embedded['wp:term'][0])を取り出してHTMLに変換している。LP側は「ブログのWordPressに何が入っているか」を一切知らなくてよく、REST APIが返すJSONの形だけを知っていればよい。この「呼び出す側が実装の詳細を知らなくて済む」性質は、システム同士を疎結合に保つ上でAPI連携全般に共通する利点である。

ファイルキャッシュで毎回のAPI呼び出しを避ける

REST APIへのHTTPリクエストは、LPのページ読み込みのたびに毎回発生させると、ブログ側WordPressへの負荷とLP自身の表示速度の両方に影響する。そこで wpmm_fetch_latest_posts() は、取得結果を sys_get_temp_dir() 配下にJSONファイルとして1時間キャッシュしている。キャッシュが新鮮なうちはAPIを呼ばずにファイルから即座に返し、1時間を超えたら再取得してキャッシュを更新する。

ここで注意深く設計されているのが失敗時の振る舞いである。REST APIへのリクエストが失敗した場合(ブログ側WordPressが一時的にダウンしている、タイムアウトした等)、いきなり空配列を返すのではなく、まず古いキャッシュが残っていればそれを使うという一段階のフォールバックを挟んでいる。それでも使えるキャッシュがなければ、最終的に空配列を返し、呼び出し元のLPは「最新の記事」セクション自体を描画しない。新しい情報が出せないなら古い情報で我慢し、それすらなければ黙って何も出さない、という段階的な劣化のさせ方になっている。

書き込み系エンドポイントには認証が要る

投稿の作成・更新・削除など、サイトの状態を変える操作を行うエンドポイントは、匿名アクセスを許さない。WordPressのREST APIでは、ログイン中のセッションに紐づくnonce(管理画面内のJavaScriptから叩く場合)や、Application Passwords(WordPress 5.6以降の標準機能・外部アプリケーション用に発行するユーザー名+専用パスワードの組)といった認証手段を使って、リクエストを送信しているのが誰かをサーバー側が検証する。

読み取り専用の公開情報を扱う posts エンドポイントのようなGETリクエストと、状態を変更するPOST/PUT/DELETEリクエストとで要求される認証レベルが根本的に異なる、という区別は、REST API全般(WordPressに限らず)を理解する上での基本的な前提になる。「このエンドポイントは誰でも読めるべきか、それとも本人確認が必要な操作か」を最初に切り分けて考えると、設計の見通しがよくなる。

まとめ

論点 要点
/wp-json/ WordPress 4.7以降、プラグイン不要で標準搭載。エンドポイント一覧をJSONで返す
/wp/v2/posts 公開済み投稿を取得する代表的なエンドポイント。認証なしでGET可能
_embed アイキャッチ画像・タクソノミー項目などの関連データを1リクエストにまとめて取得。追加リクエストの発生を防ぐ
実例(blog_latest.php LPがブログ側WordPressのREST APIを外部から叩き、内部実装を知らずに最新記事情報を取得
キャッシュ設計 1時間のファイルキャッシュ+失敗時は古いキャッシュへ段階的フォールバック
書き込み系の認証 GET(読み取り)とPOST/PUT/DELETE(書き込み)で要求される認証レベルが異なる

WordPressのREST APIは、プラグインを追加せずとも「外部のシステムからWordPressのデータを安全に覗く窓」として機能する。読み取り専用のエンドポイントから使い始め、キャッシュと失敗時のフォールバックをセットで設計しておくと、連携先のWordPressが一時的に不調でも、呼び出し側のシステム全体を巻き込んで落ちるのを防げる。