Help us understand the problem. What is going on with this article?

《WordPress》2017年末にWP REST API で取得してVue.jsで描画するまでのまとめ。

More than 1 year has passed since last update.

WordPress では WP REST API で投稿/メタデータ/ユーザーなどを、jsonとしてまとめてくれるので、JavaScriptで取得して描画するところまでを簡単に実装することができます。はじめかた、jsonのカスタマイズ、Vue.js で非同期取得して描画、までに最低限必要なことのまとめです。

ググると古い情報がたくさん出てきて困ったので、この記事を書きました。
できれば、ここはメンテナンスしたいと思います🍟

  • WordPress 4.8.2
  • WP REST API 2.0-beta15

上記の環境での情報です。

はじめる

「WordPress はアプリケーションフレームワークへと生まれ変わろうとしています。」という文章から始まっているのが印象的ですね。

プラグインをインストール/有効化したら、例えば以下のURLにアクセスすると、投稿のjsonを確認できます。

http://example.com/wp-json/wp/v2/posts/

基本的なtips

カスタム投稿、タクソノミを有効にする

カスタム投稿やタクソノミを有効にするには、CPT UI を利用している場合ですが、「REST API で表示」を Trueにします。

http://example.com/wp-json/wp/v2/POST_TYPE/

タクソノミに所属するターム一覧は、

https://example.com/wp-json/wp/v2/TERM_NAME/

という感じでjsonを取得できます。

アイキャッチ情報を取得

_embed をクエリに付加すると、アイキャッチ情報を取得できます。

http://example.com/wp-json/wp/v2/POST_TYPE?_embed

検索して取得

search= にパラメーターを渡します。

http://example.com/wp-json/wp/v2/POST_TYPE?search=vue

Vue.js で記事一覧を取得する

取得したjsonを利用してコンテンツを描画します。フレームワークの Vue.js を使うと、シンプルに非同期処理を含むコンポーネントを定義することができます。導入など省きますが、ぼくは gulp.js で webpack を動かして vue-loader で .vue を読んでいます。CSS のフレームワークには bluma を利用しています。

ページ描画時に記事一覧を取得して、load more ボタンを押すと、さらに次のページを読み込むよくあるコンポーネントです。非同期処理は axios で簡潔に書いています。

post.vue.html
<template>
  <div>
    <h2>your post</h2>
    <transition-group class="columns is-gapless is-multiline" name="fade" tag="ul">
      <li class="column is-3" v-for="post in posts" :key="post.title.rendered">
        <a :href="post.link">
          <div class="card">
            <div class="card-image">
              <figure class="image is-16by9">
                <template v-if="post._embedded['wp:featuredmedia']">
                  <img :src="post._embedded['wp:featuredmedia'][0].source_url" alt="">
                </template>
                <template v-else>
                  <img src="https://source.unsplash.com/1600x900/?web,develop" alt="">
                </template>
              </figure>
            </div>
            <div class="card-content">
              <h2 class="content" v-html="post.title.rendered"></h2>
            </div>
          </div>
        </a>
      </li>
    </transition-group>
    <button
      class="button is-primary"
      :class="[{
        'is-loading': loading,
        'is-desabled': disabled
      }]"
      :disabled="disabled"
      @click="load"
    >load more</button>
  </div>
</template>

<style scoped>
  .fade-enter-active, .fade-leave-active {
    transition: opacity .5s;
  }
  .fade-enter, .fade-leave-to{
    opacity: 0;
  }
</style>

<script>
  import axios from 'axios';

  export default {
    data() {
      return {
        posts: [],
        page: 0,
        loading: false,
        disabled: false,
      }
    },
    mounted() {
      this.page = 1;
    },
    watch: {
      page() {
        const url = `https://webmanab-html.com/wp-json/wp/v2/tip?page=${this.page}&_embed`;
        (async () => {
          try {
            const res = await axios.get(url);
            this.posts = this.posts.concat(res.data);
            this.loading = false;
          } catch (error) {
            console.log(error);
            this.empty();
          }
        })();
      }
    },
    methods: {
      load() {
        this.loading = true;
        this.page++;
      },
      empty() {
        this.loading = false;
        this.disabled = true;
      }
    },
  }
</script>

webpack.config.js
// 一部分だけ書いています

import path from 'path';

resolve: {
  // 拡張子の省略の許可
  extensions: [
    '.js',
    '.vue'
  ],
  // パス通しやすくしとく
  alias: {
    'Vue$': 'vue/dist/vue.common.js',
    'Component': path.resolve(__dirname, 'src/assets/js/component/'),
  },
}

レスポンスを増やす

register_rest_field 関数を使って、REST APIは簡単に拡張できます。

投稿のカスタムフィールドを出力する

プラグインのACFを利用している前提です。

function.php
function wp_rest_api_cf() {

  $params = array(
    'get_callback'    => function($data, $field, $request, $type) {

      if (function_exists('get_fields')) {

        return get_fields($data['id']);

      }
      return [];

    },
    'update_callback' => null,
    'schema'          => null,
  );


  $post_types = get_post_types( '', 'names' );

  foreach ( $post_types as $post_type ) {

    register_rest_field( $post_type, 'fields', $params );

  }

}
add_action( 'rest_api_init', 'wp_rest_api_cf');


"fields": {
  "demo": false,
  "demo-url": "",
  "primary-tag": "javascript"
},

投稿が所属するタームを全て出力する

デフォルトではどのタームに属しているか出力されません。投稿が所属するタクソノミとそのタームを全て取得します。

function.php
function wp_rest_api_terms() {

  $params = array(
    'get_callback'    => function($data, $field, $request, $type) {

      if (function_exists('get_the_terms')) {

        $post = get_post( $data['id'] );
        $post_type = $post->post_type;
        $taxonomies = get_object_taxonomies( $post_type, 'objects' );
        $terms = array();
        foreach ( $taxonomies as $taxonomy_slug => $taxonomy ) {

          $terms[$taxonomy->label] = get_the_terms( $data['id'], $taxonomy_slug );

        }
        return $terms;

      }

      return [];

      },
    'update_callback' => null,
    'schema'          => null,
  );

  $post_types = get_post_types( '', 'names' );

  foreach ( $post_types as $post_type ) {

    register_rest_field( $post_type, 'terms', $params );

  }

}
add_action( 'rest_api_init', 'wp_rest_api_terms');



"terms": {
  "tips": [
    {
      "term_id": 29,
      "name": "javascript",
      "slug": "javascript",
      "term_group": 0,
      "term_taxonomy_id": 29,
      "taxonomy": "tips",
      "description": "",
      "parent": 0,
      "count": 31,
      "filter": "raw"
    },
    {
      "term_id": 30,
      "name": "jQuery",
      "slug": "jquery",
      "term_group": 0,
      "term_taxonomy_id": 30,
      "taxonomy": "tips",
      "description": "",
      "parent": 0,
      "count": 11,
      "filter": "raw"
    },
  ],
  "writer": [
    {
      "term_id": 8,
      "name": "uto usui",
      "slug": "uto-usui",
      "term_group": 0,
      "term_taxonomy_id": 8,
      "taxonomy": "writer",
      "description": "",
      "parent": 0,
      "count": 493,
      "filter": "raw"
    }
  ]
},

古い情報について

大抵2016年に書かれている情報は、動かないことが多いです。ググると上位に出てくる日本語記事はこのケースが多いので注意したいです。あたりまえですが、公式のドキュメントを読むのが一番ですね。

例えば、

  • filter[]= クエリは使えない。

  • register_api_field は使えない、 register_rest_field 関数を使う。

おわります。

uto-usui
臼井優斗 🇯🇵 I’m Yuto 👨🏻‍💻 Frontend Developer - VOUGE, GQ, WIRED - Condé Nast Japan/Nuxt, WebGL/Guitar, Photograph, Woodwork/吉祥寺 ⇄ 渋谷 🐈 🌸 🎸 📸 📚 🍎
https://uto-usui.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした