LoginSignup
117
127

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-10-22

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 関数を使う。

おわります。

117
127
2

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
117
127