ナム山

家最高 今年一年でサックスが吹けるようになるか観測中

REST APIでWordpressの更新情報を別ドメインから取得する(JSONPを使用)

REST APIについては見聞きしていたが初めて触るので、とりあえず最新10件取得でもしてみるかと書いてみる。
_embedオプションでサムネ画像も含んだjsonを返してくれる。
参考:https://webtatan.com/blog/wordpress/wp-rest-api-v2-json

最初のコード

$(function(){
  var url = "//www.testsite/wp-json/wp/v2/posts?_embed";
  $.get(url, function(data){
    var html = '';
    for(var i = 0;i<data.length;i++){
      var id = data[i].id;
      var title = data[i].title.rendered;
      var url = data[i].link;
      var pic = data[i]._embedded['wp:featuredmedia'][0]['media_details']['sizes']['full']['source_url'];
      html += '<li><a href="' + url + '">';
      html += 'title:' + title + '/ id:' + id + '/ 写真:';
      html += '<img src="' + pic + '">'
      html += '</li>'
    }
    $('#div').append(html);
  });
});
error処理も適当に

結果
通常のajax通信だとクロスドメイン問題でエラーが出る。
(CODEPENで試していたけどCODEPENは問題ないのね)

やったこと - 学んだこと

  • JSONPで取得する方向へ変更 - JSONPの概要理解
  • エラー処理を検討する - 取得パラメータの調整
JSONPで取得する

お、これがクロスドメイン問題か、と調べてPHPで処理するかJSONPで取得する必要があるのは分かった。
参考:http://tsujimotter.info/2013/01/03/jsonp/
参考:https://debug-life.net/entry/1653

JSONPの仕組みをちゃんと理解していなかったので調べてみると、
そもそも仕組みが違って、データをcallbackの引数として渡してるとのこと。
先にfunctionが用意されてるのが気持ち悪かったけどscriptで処理されているということなのか。
CDNとほぼ同じということかと理解。

コードに戻る。
今回の仕様は「大カテゴリーごとに最新記事を1件出力する」というものだったので、
切り分ける条件ごとに、用意する関数の分だけ読み込みが必要になってしまった。
その分処理を少なくするために取得パラメータで調整を試みることにした。

エラー処理を検討する

エラー処理、と銘打ったのは上記と関係あるが、そもそもデフォルトで引っ張ってくるデータの量が多いので、
「最新1件」をそもそも「各大カテゴリーごとに最新1件だけ取得する」ことにしてフィルタリングした。
データが返ってこない=記事がないのでこれを条件分岐に利用することにした(*1)
JSONPを取得する条件をまとめると

  • _embedオプション付き(サムネ画像も必要なため)で
  • 該当大カテゴリー(つまり複数小カテゴリー)の記事を(categories=)
  • 最新1件だけ(per_page=)を
  • 各checkData関数へ渡すためにJSONPで(_jsonp)取得する。

カテゴリーはそのまま(categories)で良いみたいですが、
複数カテゴリーはコンマつなぎで問題なさそうでした。
参考:https://ja.wp-api.org/

最終的なコード

html - 末尾に追加

<script src="//www.testsite/wp-json/wp/v2/posts/?_jsonp=checkData01&_embed&categories=10,11&per_page=1"></script>
<script src="//www.testsite/wp-json/wp/v2/posts/?_jsonp=checkData02&_embed&categories=12,13&per_page=1"></script>

js

new_Array = [];

function checkData01( data ) {
  if(data.length){
    new_Array.push(data);
  }else{
    new_Array.push(null);//*1記事の情報が0
  }
}
function checkData02( data ) {
  if(data.length){
    new_Array.push(data);
  }else{
    new_Array.push(null);
  }
}

$(window).on('load', function(){
  if( new_Array.indexOf(null) == -1 ){
    var len = new_Array.length;
    for(var i=0; i<len; i++){
      var html = '';
      var catname = new_Array[i][0]._embedded['wp:term'][0][0]['name'];//カテゴリ名
      var title = new_Array[i][0].title.rendered;//タイトル
      var pl = new_Array[i][0].link;//パーマリンク
      var pic = new_Array[i][0]._embedded['wp:featuredmedia'][0]['media_details']['sizes']['medium']['source_url'];//サムネ画像

      html += '<li><a href="' + pl + '" target="_blank"><img src="' + pic + '"></a>'
      html += '<span>' + catname + '</span><span>' + title + '</span></li>';
      $(html).appendTo('#data');
    }
  }
});

コードの説明 - まとめ

  • 空の配列を用意する
  • 返ってきたJSONPの情報があれば配列へ、なければnull *1
  • loadが終わったら上記配列をチェックして、一つもnullがなければ
  • それぞれ解析したJSONから欲しい情報を取得して成型する

(親のdivとか差し込みたいulとか用意してある前提)

*1明示的にnullにした理由として、
data.lengthで判定すると、明らかにありえない小カテゴリーを入力しても配列自体は空で返ってきてしまうから。
そうなるとArray(0)でも処理が進んでしまい、いざjsonを掘っていく段階で[.titleってなに?]と怒られが発生した。
そのため明示的にnullを渡して、1つもnullがなければ、という条件で成形の関数を動かすことにした。

JSONPはscriptで、用意したコールバック関数に引数として渡している。
個人的に、成形を後回しにして最後に一気に組むようにしたのはちょっと成長を感じた。
ドラキーバブルスライムくらいにはなったんちゃいますか。