はじめに
今後流行するであろう、GraphQL+Headless CMSについて調べていたところ、WordPressでもGraphQLを実現できるプラグインがあることを知り、試してみました。まだ、日本語のドキュメントが少ないので、ここに記事にしました。
検証した環境
- macOS 10.13.16
- Docker
- WordPress5.2.2
- Dockerのコンテナを使っています
インストール
-
wp-graphql
はプラグインディレクトリからインストールすることができません(07/30時点) - プラグインのソースコードがGitHubに公開されていますので、それを使います
インストールするプラグイン
-
wp-graphql
- WordPressをGraphQLサーバにするプラグイン
-
wp-graphiql
- WordPressの管理画面上で、GraphQLを実行できるプラグイン
- WordPressの管理画面上で、GraphQLを実行できるプラグイン
手順
WordPressのプラグインディレクトリに移動します
cd html/wp-content/plugins
ディレクトリは各自の環境に応じて読み替えてください
git cloneします
git clone https://github.com/wp-graphql/wp-graphql.git
git clone https://github.com/wp-graphql/wp-graphiql.git
- ReleasesからZIPをダウンロードしたほうがよいと思いますが、ローカル環境だし、今後のバージョンアップ時にgit pullの方が簡単なので、git cloneにしました
WordPress にログインして、プラグインを有効化します
GraphiQLからGraphQLを実行します
メニューに、GraphiQLが表示されていますので、クリックします
ウィンドウの左側に以下のクエリを貼り付けます。
{
posts{
edges {
node { postId title link date }
}
}
}
上の矢印ボタンをクリックすると実行されます。
ウィンドウの右側にクエリの結果が表示されれば動作しています。
このIDEですが、かなり賢く補完してくれるので重宝すると思います。
クエリのサンプル
- 投稿と固定ページのデータを取得するためのクエリサンプルです
1件の投稿を取得する
{
postBy(postId:1){
title date link
}
}
1件の固定ページを取得する
{
pageBy(pageId:2){
title date link
}
}
直近5件の投稿を取得する
{
posts(first:5) {
edges {
node { postId title link date }
}
}
}
直近5件の投稿をカテゴリ付きで取得する
{
posts(first:5) {
edges {
node { postId title link date
categories {
edges { node { id name } }
}
}
}
}
}
カテゴリID:2の直近5件の投稿を取得する
{
posts(first:5,where:{categoryId: 2}) {
edges {
node { postId title link date
categories {
edges { node { id name } }
}
}
}
}
}
1件と投稿と1件の固定ページを取得する
{
postBy(postId:1) {
postId title link date
},
pageBy(pageId:2){
title date link
}
}
- REST APIだと2回APIをコールしないといけないが、GraphQLだと1回ですみますね
curlからアクセスする場合
- curlからアクセスする場合、パーマリンク設定が基本になっていると、/graphqlが404エラーになります。基本以外の設定に変更します
- httpクライアントであるcurlからGraphQLを実行する場合はこのようなシェルを用意しておきます
#!/bin/sh
curl \
-X POST \
-H 'content-type: application/json' \
--data @- \
http://localhost/graphql
次にクエリ部分をjsonファイルにしておきます
{
"query":"{ posts { edges { node {postId title} } } }"
}
jsonファイルを標準入力でシェルに渡します
sh curl.sh < get-posts.json
クエリ部を別ファイル化しておくことで、いろんなクエリを楽に実行することができると思います
REST API との比較
REST API
- WordPressにはREST APIが搭載されています。そのAPIで投稿を取得するとこのようになります。レスポンスはフォーマットかけてます。レスポンスが長いですね〜
リクエスト
curl http://localhost/wp-json/wp/v2/posts/1
レスポンス
{
"id": 1,
"date": "2019-07-30T16:38:46",
"date_gmt": "2019-07-30T07:38:46",
"guid": {
"rendered": "http:\/\/localhost\/?p=1"
},
"modified": "2019-07-31T15:47:50",
"modified_gmt": "2019-07-31T06:47:50",
"slug": "hello-world",
"status": "publish",
"type": "post",
"link": "http:\/\/localhost\/2019\/07\/30\/hello-world\/",
"title": {
"rendered": "Hello world!"
},
"content": {
"rendered": "\n<p>WordPress \u3078\u3088\u3046\u3053\u305d\u3002\u3053\u3061\u3089\u306f\u6700\u521d\u306e\u6295\u7a3f\u3067\u3059\u3002\u7de8\u96c6\u307e\u305f\u306f\u524a\u9664\u3057\u3001\u30b3\u30f3\u30c6\u30f3\u30c4\u4f5c\u6210\u3092\u59cb\u3081\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n",
"protected": false
},
"excerpt": {
"rendered": "<p>WordPress \u3078\u3088\u3046\u3053\u305d\u3002\u3053\u3061\u3089\u306f\u6700\u521d\u306e\u6295\u7a3f\u3067\u3059\u3002\u7de8\u96c6\u307e\u305f\u306f\u524a\u9664\u3057\u3001\u30b3\u30f3\u30c6\u30f3\u30c4\u4f5c\u6210\u3092\u59cb\u3081\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n",
"protected": false
},
"author": 1,
"featured_media": 0,
"comment_status": "open",
"ping_status": "open",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [
2,
1
],
"tags": [],
"_links": {
"self": [
{
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/posts\/1"
}
],
"collection": [
{
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/posts"
}
],
"about": [
{
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/types\/post"
}
],
"author": [
{
"embeddable": true,
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/users\/1"
}
],
"replies": [
{
"embeddable": true,
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/comments?post=1"
}
],
"version-history": [
{
"count": 1,
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/posts\/1\/revisions"
}
],
"predecessor-version": [
{
"id": 9,
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/posts\/1\/revisions\/9"
}
],
"wp:attachment": [
{
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/media?parent=1"
}
],
"wp:term": [
{
"taxonomy": "category",
"embeddable": true,
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/categories?post=1"
},
{
"taxonomy": "post_tag",
"embeddable": true,
"href": "http:\/\/localhost\/wp-json\/wp\/v2\/tags?post=1"
}
],
"curies": [
{
"name": "wp",
"href": "https:\/\/api.w.org\/{rel}",
"templated": true
}
]
}
}
GraphQL
リクエスト
curl http:/localhost/graphql -X POST -H 'content-type: application/json' --data '{ "query" : "{ postBy(postId:1) { postId title link date }}" }'
レスポンス
{"data":{"postBy":{"postId":1,"title":"Hello world!","link":"http:\/\/localhost\/2019\/07\/30\/hello-world\/","date":"2019-07-30T16:38:46"}}}
こんなにシンプルなレスポンスになります。すっきりできそうだ
WordPressのGraphQLプラグインの使い所
- WordPressで構築したサイトでテンプレート(function.phpあたり)を作れる人がいない。または、時間が取れない
- WordPressで管理しているデータを別サイトで使いたい
このような状況であれば、このプラグインを使って、JSからGraphQLを使ってデータを取得すれば実装がすぐにできると思います。まあ、REST APIでもいいですが、GraphQLなら初回アクセス時に1回のAPIで必要なデータを取得しておき、それをローカルストレージに格納して使い回すなんてこともできると思います。
WordPressをGraphQL+Headless CMSで使う
最初からHeadless CMSと使うなら、私なら別のCMSを選択すると思います。ただし、国産でそのようなCMSがないので、海外のCMSを採用することになります。そうした場合、CMS管理画面のメニューが英語になったり、サポートも日本語では受けれなくなると思います。そういった状況では導入が困難になると話は変わってきます。
WordPressの知名度と無償、検索すればなんかしら情報が出てくる、使える人が多いことを考慮に入れると、選択肢に入ってきますね。
最後に
- 今回はセキュリティまわりに触れていません。GraphQLを使ってデータの登録や削除もできますので、本番環境に適用する場合にはセキュリティには注意しましょう。さすがに認証が必要と思われますが、未検証です。
- 今回使ったプラグインは、まだ1.0として公開されていません。そのあたりにも注意しましょう
- 登録や削除のクエリは別の機会に試してみたいと思います