jtk

EJSで使う構文まとめ

会社でGulpでEJS触わる機会が多いので、よく使う構文をまとめておこうと思います。

f:id:jotaki:20191108143317p:plain

基本

.html

<% var ejsRoot = './'; %>
<%- include(ejsRoot + '_module/ejsFileName'); %>

.ejs

<!-- .htmlで出力するHTML -->

パラメータ指定

ボタンのコンポーネントをejs化するサンプル

.html

<%- include(ejsRoot + '_module/component/button', {
  buttonColor: 'red',
  buttonLink: '/path/',
  buttonText: 'ボタンのテキスト'
}); %>

.ejs

<p class="button button--<%= buttonColor %>">
  <a href="<%= buttonLink %>">
    <%= buttonText %>
  </a>
</p>

.html側でパラメータ指定がない場合はGulpでコンパイルエラーになるのを回避するには、

<% if( typeof buttonColor!='undefined' ){ %>
  <!-- ここに `buttonColor: 'hogehoge' が定義されている場合 -->
<% } else { %>
  <!-- それ以外の場合 -->
<% } %>

などとすると分岐してエラー回避できる。

参考: Using "if" to check variable before usage results in Error, Undefined · Issue #90 · tj/ejs

出力するバナーの個数をパラメータで指定する

.html

<%- include(ejsRoot + '_module/component/banner', { item: 4 }); %>

.ejs

<ul>
  <% for (var i=0; i<item; i++) { %>
    <li>
      <a href="#">
        <img src="banner.png" alt="">
      </a>
    </li>
  <% } %>
</ul>

パンくずをパラメータで指定する

<%- include(ejsRoot + '_module/component/breadcrumb', {
  navigationList: [
    {
      path: '/',
      label: 'ホーム'
    },
    {
      path: '/parent/',
      label: '親階層ページ'
    },
    {
      path: '',
      label: '子階層ページ'
    }
  ]
}); %>

.ejs

<ol>
  <% for (var key in navigationList) { %>
  <%
    // .html 側に定義された path と label をループしてパンくずを生成
    var path = navigationList[key].path;
    var label = navigationList[key].label;
  %>
  <li>
    <% if ( path === '' ) { %>
      <span class="current">
        <%= label %>
      </span>
    <% } else { %>
      <a href="<%= path %>">
        <%= label %>
      </a>
    <% } %>
  </li>
  <% } %>
</ol>

参考: テンプレートエンジンEJSで使える便利な構文まとめ - Qiita

2019年10月 振り返り

結果

ブログ

目標:月 12 回(週 3 回)更新
結果:月 6 回 更新

読書

目標:月 1 冊
結果:月 0 冊

反省点など

本も特に興味を持てるものがなかったのですが、習慣づけなきゃですね

来月に向けて

結局Nuxtでやろうと思ってたものはVueオンリーでやることになりそう 11月中に公開までしたい。また使ったものに関してブログにまとめる

カスタム投稿 REST APIで取得するJSONを並び替えプラグイン通りにする

f:id:jotaki:20190206105446p:plain

https://siteUrl.com/wp-json/wp/v2/POST-TYPE-NAME/REST APIを叩くと順番がデフォルト(投稿日順?)になってしまうので、これを並び替えプラグイン通りに並べ替えたい。

ぴったしの記事がありました
Intuitive Custom Post Orderの並び順をWP-REST-APIに反映する - aircolor memolog

カスタム投稿の場合は下記のようにする( POST-TYPE-NAME にポストタイプを指定 )

<?php
add_filter( 'rest_POST-TYPE-NAME_query', function( $args, $request ) {
  $args['order'] = 'ASC';
  $args['orderby'] = 'menu_order';
  return $args;
}, 10, 2 );

タクソノミーの場合も同様

<?php
add_filter( 'rest_TAXONOMY-NAME_query', function( $args, $request ) {
...

他参考

ACF オプションページのREST APIエンドポイント

f:id:jotaki:20191008144612p:plain

ACFオプションページのエンドポイントがうまくいかなかったのでメモ
公式ドキュメント: https://github.com/airesvsg/acf-to-rest-api
同じようなissue: https://github.com/airesvsg/acf-to-rest-api/issues/184

登録はfunctions.phpに通常通り記述

<?php
// ...
if( function_exists('acf_add_options_page') ) {
  $option_page = acf_add_options_page(array(
    'page_title' => 'PAGE-NAME',
    'menu_title' => 'PAGE-NAME',
    'menu_slug' => 'SLUG-NAME',
    'capability' => 'edit_posts',
    'redirect' => false
  ));
}
// ...

ドキュメントに /wp-json/acf/v3/options/{id}/ とあるので
https://{site_url}.com/wp-json/acf/v3/options/{id}/
を叩いてみても acf:{} と空が返ってくる...

こちら によると

/wp-json/acf/v3/options/{id}/
ではなく
/wp-json/acf/v3/options/options/
だとうまくいくとのこと。

https://{site_url}.com/wp-json/acf/v3/options/options/
が正解でちゃんと返ってきました。
ただこれだとすべてのオプションページのフィールドを含んでいるみたいです。
オプションページ登録部分が悪いのか、環境依存なのかは謎なままですがとりあえず取得まではこれでできるという感じでした。

node.js の切り替えを nodebrew ではなく nodenv で行う

nodebrew はプロジェクトごとに切り替えがしづらいので、 nodenv のがいいらしい。 導入は こちら 通りでいけました

リスト表示

$ nodenv versions

バージョン指定でインストール

$ nodenv install 10.15.0
$ nodenv install 12.11.0

デフォルトで使用するバージョンを指定

$ nodenv global 12.11.0

プロジェクトごとに使用するバージョンを指定

$ cd [project folder]
$ nodenv local 10.15.0
$ nodenv local 12.11.0

これでプロジェクトフォルダに .node-version ファイルが追加されているはず
バージョン確認

$ node -v

nodebrew の削除

# パス 削除
$ export PATH=$HOME/.nodebrew/current/bin:$PATH
$ export PATH=$HOME/.nodebrew/current/bin/npm:$PATH

# nodebrew 削除
$ brew uninstall nodebrew

最後に、 ~/.nodebrew ディレクトリを削除

参考:

REST API のスキーマにリピーターフィールドの画像データを格納する

f:id:jotaki:20191008144612p:plain

ACF to REST API を使えば REST API でACFの値が取得できますが、カスタマイズした形でカスタムフィールドの値を追加する方法です。

例えばACFフィールドでアップロードした画像は指定している戻り値がREST APIでも返ってきます。
image_field: リピーターの親フィールド
image_sub_field: リピーターの子フィールド(返り値 => 画像ID の場合)

...
"acf": {
    "image_field": [
      { "image_sub_field": 164 },
      { "image_sub_field": 165 },
      { "image_sub_field": 166 },
...

このままだとAPIからは画像URLなど取れないので独自で追加する必要があります。
functions.php

<?php
// ...
function register_custom_images_data() {
  register_rest_field(
    'CUSTOM_POST_TYPE_NAME', // カスタム投稿名
    'CUSTOM_REST_API_KEY',   // REST API に追加するキー
    array(
      'get_callback'    => 'get_custom_image_data',
      'update_callback' => null,
      'schema'          => null,
    )
  );
}
add_action( 'rest_api_init', 'register_custom_images_data' );
// リピーター画像取得
function get_custom_image_data( $object, $field_name, $request ) {
  $meta_fields = $object['acf']['image_field'];
  $meta = array();
  foreach ( $meta_fields as $field ) {
    $artist_images_full = wp_get_attachment_image_src( $field['image_sub_field'], 'full');
    array_push($meta, $artist_images_full);
  }
  return $meta;
}
// ...

として REST API を叩くと

...
  "CUSTOM_REST_API_KEY": [
  {
    "https:/siteUrl.com/wp-content/uploads/2019/10/sample02.jpg",
    1280,
    640,
    false
  },
  {
    "https:/siteUrl.com/wp-content/uploads/2019/10/sample01.jpg",
    1280,
    640,
    false
  },
...

となる

仮に Vue で出力するには

<ul v-for="(image,index) in post.data.CUSTOM_REST_API_KEY" :key="index">
  <li>
    <img
      :src="image[0]"
      :data-size="`${image[1]}x${image[2]}`"
      >
  </li>
</ul>

という感じで出力する

WordPress + Nuxt.js で スラッグベースのパーマリンクにルーティングする

ルーティングする という表現があっているのかどうか微妙ですが、
カスタム投稿タイプを使ったWordPressの投稿をIDベースではなくスラッグベースで実装する場合

f:id:jotaki:20190924093802p:plain

カスタム投稿: book
.vue ファイル名: /pages/book/_slug.vue
実現したいURL構造: https://hoge.com/book/[スラッグ名]

<template>
  <section>
    <pre>{{post[0]}}</pre>
    <p>id: {{post[0].id}}</p>
    <p>slug: {{post[0].slug}}</p>
    <p>date: {{post[0].date}}</p>
    <p>link: {{post[0].link}}</p>
    <h1>{{post[0].title.rendered}}</h1>
    <div v-html="post[0].content.rendered"></div>
  </section>
</template>

<script>
import axios from 'axios'
export default {
  data () {
    return {
      post: {}
    }
  },
  asyncData ({ params }) {
    // console.log(params)
    // console.log(params.slug)
    return axios.get(`https://hoge.com/wp-json/wp/v2/book?slug=${params.slug}`)
      .then(response => {
        return { post: response.data }
      })
      .catch((error) => {
        return { error: error }
      })
  }
}
</script>

結構つまってしまって、REST APIのエンドポイント、IDベースでしか記事情報が取得できないと思って
https://hoge.com/wp-json/wp/v2/book/${params.id} でid取得したあとにスラッグ取るのどうやんのかなとか思ってましたが、
https://hoge.com/wp-json/wp/v2/book?slug=${params.slug} でいけました

なのでAPI側を理解してなかったっていう話でした
参考: https://unicorn.limited/jp/item/949