【WordPress】REST APIを使って投稿する【#np2020】

WordPressのHowto記事なんていくらでもあると思いますが、多分僕の使い方がニッチで網羅している記事がなかったので備忘録程度にまとめておきます。



やりたいこと


  1. API経由でWordPressに記事を投稿したい
  2. 投稿する記事のアイキャッチ画像を設定したい
  3. 必要に応じてメディアファイルをアップロードしたい


以上3つです。


前提条件


  • PHP 7.2
  • Laravel 5.8
  • Guzzel 6.3.3



1. API経由でWordPressに記事を投稿したい


現在のバージョンのWordPressにはREST APIがデフォルトで組み込まれているので、認証さえクリア出来ればすぐにでもAPIを利用して記事の投稿などが行えます。便利ですね。

本来であればOAuth2.0を使ってきちんと処理すべきところでしょうが、今回はそこは端折ってBasic認証を使いました。きちんとセキュリティに気を配る必要がある人は、OAuthでやってください。


参考


【WordPress】2018年版 管理画面以外から投稿する2つの方法 | WP REST API 編 | ITエンジニアラボ


そして出来たコードがこちら。


<?php
$client = new \GuzzleHttp\Client([
'base_uri' => 'https://example.com/wp-json/wp/v2/'
]);
$client->post('posts',[
'auth' => [$user, $password],
'form_params' => [
'title' => 'WP REST API Example',
'content' => '<p>サンプル記事。Guzzle使用</p>',
'status' => 'publish',
'date' => '2019-07-10T20:00:00+09:00'
],
]);



APIの仕様を見ると「status」の取りうる値として「future」というのがあり、予約投稿にするためにはそれを渡す必要がある気がしますが実際には必要なく、「status」が「publish」で「date」が未来なら自動的に予約投稿、過去なら公開になります。「下書き」「レビュー待ち」の記事を投稿したいときには「status」を「draft」「pending」にします。



2. 投稿する記事のアイキャッチ画像を設定したい


アイキャッチ画像は記事を投稿するときに設定可能です。ただ、画像のIDが必要なので、記事投稿する前にメディアに追加されている必要があります。事前にメディアにアップロードしておいた画像(画像IDは1234)があり、それをアイキャッチ画像として利用したい場合、記事投稿のコードはこうなります。


<?php
$client = new \GuzzleHttp\Client([
'base_uri' => 'https://example.com/wp-json/wp/v2/'
]);
$client->post('posts',[
'auth' => [$user, $password],
'form_params' => [
'title' => 'WP REST API Example',
'content' => '<p>サンプル記事。Guzzle使用</p>',
'date' => '2019-07-10T20:00:00+09:00',
'status' => 'publish',
'featured_media' => 1234
],
]);


至ってシンプル。



3. 必要に応じてメディアファイルをアップロードしたい


例えばネット上の自分が管理出来る場所にある画像をアイキャッチ画像として利用したいという場合を考えます。その時必要なことは、

  1. 画像の取得
  2. メディアファイルとしてアップロード

です。

また、あとで記事投稿にくっつけるために画像IDも取得しておく必要があります。


全体のコードはこんな感じ。


<?php
$client = new \GuzzleHttp\Client();
$response = $client->get('https://example.com/sample.jpg');
$image = $response->getBody()->getContents();
$client = new \GuzzleHttp\Client([
'base_uri' => 'https://example.com/wp-json/wp/v2/'
]);
$response = $client->post('media',[
'auth' => [$user, $password],
'headers' => [
'Content-Disposition' => [
'form-data; filename=sample.jpg'
]
])
,'multipart' => [
[
'name' => 'file',
'contents' => $image,
'filename' => 'sample.jpg',
],
]
]);
if(preg_match('/(\d+)$/',$response->getHeader('Location')[0],$matches)){
$media_id = (int) $matches[1];
}


前半部分は普通に画像を読み込んでいるだけ。後半部分で読み込んだ画像をメディアとしてアップロードしています。


正直、送信しているパラメータには自信がありませんが、返ってきたエラーを元に試行錯誤した結果これで上手く行くようになりました。ヘッダーとして「Content-Disposition」というヤツを送っているのがキモです。

参考


wordpress – WP Rest API upload image – Stack Overflow
WP REST API v2.0-beta7以降でmediaへ画像をアップロード : WordPress – FindxFine




まとめ


これらを組み合わせることで、

  • 画像を取得してアイキャッチ画像として使用した記事を投稿する

といったことが出来るようになりました。