LoginSignup
8
9

More than 1 year has passed since last update.

WordPress.com の投稿を REST API で取得して Vue.js でいい感じに表示してみる

Last updated at Posted at 2019-01-13

こんな要件を想定

  • 静的 HTML でサイトを運用
  • トップページ(index.html)にちょっとしたお知らせ(1 件 1~2 行程度)を表示させたい
  • HTML の知識がなくてもお知らせの追加・編集・削除ができるように

わざわざ CMS をセットアップするのはちょっと大仰なので、セキュリティアップデートなどの煩雑さから解放される WordPress.com を使って

  • WordPress.com でお知らせコンテンツを管理
  • REST API 経由で投稿を取得
  • 投稿タイトルの一覧を index.html 上にリスト表示

という解決策をとってみます。Vue.js と axios の組み合わせでわりとすっきり実装できました。

サーバ要件

  • PHPが動作すること(要 cURL)
    index.html のあるサーバと同一である必要はありません

ドキュメント

REST API Resources | Developer Resources
https://developer.wordpress.com/docs/api/

実装手順

REST API を使うための API キーを取得

WordPress.com にログインした状態で Developer サイト( https://developer.wordpress.com/ )にアクセス。

Developer サイトの「My Apps」メニューをクリックし https://developer.wordpress.com/apps/ に移動。

「Create New Application(新規アプリケーション作成)」ボタンをクリックして下記を入力。

  • Name
    任意のアプリケーション名
  • Description
    任意の説明文
  • Website URL
    自身の公開サイト URL(http://localhost などローカルの URL も可)
  • Redirect URLs
    リダイレクトURL(開発/ステージング/本番 複数可)
  • Javascript Origins
    JavaScriptを設置するURL(開発/ステージング/本番 複数可)

アクセストークンを取得

外部のスクリプトから投稿データを取得できるように OAuth の設定をします。

Howdy! {YOUR_APP_NAME} would like to connect to your WordPress.com site.

というようなメッセージが出るはずなので「Approve」ボタンをクリック。

トークンの自動生成を設定

取得したトークン文字列を JS ファイルにベタ書きしてもいいのですが、ドキュメント「OAuth2 Authentication | Developer Resources」 内に

Tokens currently last two weeks and users will need to authenticate with your app once the token expires. Tokens are returned via the hash/fragment of the URL.

トークンは 2 週間で無効になるという一文が!

そこでドキュメントの教えに沿って、PHP を使ってトークンを自動生成するように設定します。ファイル名は get-token.php としました。

get-token.php

<?php

// JavaScript の実行ドメインと PHP スクリプトを置くドメインが違う場合は Access-Control-Allow-Origin を設定する必要あり


// cURL を使ってトークンを取得
$curl = curl_init( 'https://public-api.wordpress.com/oauth2/token' );
curl_setopt( $curl, CURLOPT_POST, true );
curl_setopt( $curl, CURLOPT_POSTFIELDS, [
        
	// YOUR_CLIENT_ID に My Apps で作成したアプリケーションの Client ID を記述
	'client_id' => YOUR_CLIENT_ID,

	// YOUR_CLIENT_SECRET に My Apps で作成したアプリケーションの Client Secret を記述
	'client_secret' => 'YOUR_CLIENT_SECRET',

	'grant_type' => 'password',

	// YOUR_WP_USERNAME に WordPress.com サイトのユーザー名を記述        
	'username' => 'YOUR_WP_USERNAME',

	// YOUR_WP_PASSWORD に WordPress.com サイトのパスワードを記述                
	'password' => 'YOUR_WP_PASSWORD',
] );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1);
$auth = curl_exec( $curl );
$auth = json_decode( $auth );
$access_key = $auth->access_token;

echo $access_key;

get-token.php をリモートにアップロードし http://example.com/get-token.php をたたいてトークン文字列が表示されれば OK。

URL 直打ちでトークン文字列が丸裸になるので、作成したアプリケーションの「Javascript Origins」や、get-token.php の「Access-Control-Allow-Origin」の設定を適切に行ってください。

Vue.js と axios の読み込み

ここはさくっと CDN の力を借りましょう(Vue.js のバージョンは本記事執筆時点のもの)。

index.html

<script src="//cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="//unpkg.com/axios/dist/axios.min.js"></script>

投稿データ取得のための JS ファイルを設置

WordPress.com から投稿を取得する JS ファイル(get-posts.js)の例です。

定数 wpUrl 内の example.wordpress.com は投稿を取得したい WordPress.com サイトのドメイン、同 phpPath 内の example.com は get-token.php を設置したドメインにそれぞれ書き換えてください。

get-posts.js

'use strict';

const wpUrl   = 'https://public-api.wordpress.com/rest/v1.1/sites/example.wordpress.com/posts/';
const phpPath = 'https://example.com/get-token.php';


// REST API 経由で投稿データを取得
const getWpPosts = function(data) {	
	axios.get(wpUrl, {
		headers: {'Authorization': 'BEARER ' + data}
	})
	.then(function (response) {
		initVue(response.data);
	})
	.catch(function (error) {
		initVue(error);
	});	
};


// アクセストークン文字列を取得
const getWpToken = function() {	
	axios.get(phpPath, {
		responseType: 'text'
	})
	.then(function (response) {
		getWpPosts(response.data);
	})
	.catch(function (error) {
		console.log(error);
	});	
};


// Vue インスタンスの生成
function initVue(data) {
	if (data.hasOwnProperty('posts')) {
		if (data.posts.length > 0) {
			new Vue({
				el: '#posts',
				data: {
					posts: data.posts,
					type: 'posts'
				}
			});
		}
		else {
			new Vue({
				el: '#posts',
				data: {
					type: 'no-posts'
				}
			});
		}
	}
	else {
		new Vue({
			el: '#posts',
			data: {
				type: 'errored'
			}
		});
	}
}


window.onload = function () {
	getWpToken();
}

get-posts.js ができたら index.html に読み込みます。ここでは index.html と同階層にある js ディクレトリ内に get-posts.js を置くような設定にしました。

index.html

<script src="//cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="//unpkg.com/axios/dist/axios.min.js"></script>
<script src="./js/get-posts.js"></script>

Vue.js でページ内にレンダリング

取得結果を表示させたい箇所を <div id="posts">...</div> とマークアップした例です。

index.html

<div id="posts">
	<ul v-if="type === 'posts'" v-cloak>
		<li v-for="post in posts">{{ post.title }}<br> 
		({{ post.date }})</li>
	</ul>	
	<p v-if="type === 'no-posts'" v-cloak>現在公開中のお知らせはありません。</p>
	<p v-if="type === 'errored'" v-cloak>何らかの原因でお知らせのデータが取得できませんでした。</p>
</div>

v-cloak ディレクティブを付加したので、index.html が読み込む CSS ファイルに下記を追記しておきます。

[v-cloak] {
	display: none;
}

日付表示もいい感じにする

これでひととおり実装できましたが {{ post.date }} で示した投稿日の日付が

2019-01-01T00:00:00+09:00

というような表示になってしまうので、日付処理ライブラリ Moment.js を使っていい感じに変換することにします。Moment.js も CDN でさくっと読み込みましょう(バージョンは本記事執筆時点のもの)。

index.html の JS 読み込み箇所

<script src="//cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="//unpkg.com/axios/dist/axios.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.js"></script>
<script src="./js/get-posts.js"></script>

index.html<div id="posts">...</div>

【変更前】

<div id="posts">
	<ul v-if="type === 'posts'" v-cloak>
		<li v-for="post in posts">{{ post.title }}<br> 
		({{ post.date }})</li>
	</ul>	
	<p v-if="type === 'no-posts'" v-cloak>現在公開中のお知らせはありません。</p>
	<p v-if="type === 'errored'" v-cloak>何らかの原因でお知らせのデータが取得できませんでした。</p>
</div>

【変更後】

<div id="posts">
	<ul v-if="type === 'posts'" v-cloak>
		<li v-for="post in posts">{{ post.title }}<br> 
		({{ post.date | moment }})</li>
	</ul>	
	<p v-if="type === 'no-posts'" v-cloak>現在公開中のお知らせはありません。</p>
	<p v-if="type === 'errored'" v-cloak>何らかの原因でお知らせのデータが取得できませんでした。</p>
</div>

get-posts.js の function initVue() 内

【変更前】

if (data.posts.length > 0) {
	new Vue({
		el: '#posts',
		data: {
			posts: data.posts,
			type: 'posts'
		}
	});
}

【変更後】

if (data.posts.length > 0) {
	new Vue({
		el: '#posts',
		filters: {
			moment: function(date) {
				if (!date) return ''
				return moment(date).format('YYYY/M/D');
			}
		},
		data: {
			posts: data.posts,
			type: 'posts'
		}
	});
}

moment(date).format('YYYY/M/D'); が文字列を指定している箇所です。表示例は Moment.js のドキュメントを参照してください。

運用にあたっての tips 的なもの

WordPress.com はお知らせコンテンツ管理のためだけに使うので、WordPress.com サイト自体は非公開の運用とするのがおすすめです。

また、WordPress.com アカウントの通知設定もよしなに済ませるとよいでしょう。

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9