More than 1 year has passed since last update.

WP REST APIを使いたい

WordPress4.1から標準機能になるという、WP REST APIプラグインがすごく面白い。これを使えば、WordPressのテンプレートタグにとらわれず、WordPressをCMSとしたサイトを自由に作れるのではないか。
それをテンプレート機能もあるRactive.jsでやったら楽なんじゃないかと。

ページスラッグからpageのJSONデータを取得して表示内容を置換する例

html
<div id="main-menu"></div>
<div id="pages"></div>
template
<script id="menuTemplate" type="text/ractive">
<ul class="nav nav-pills">
    {{#menu}}
    <li class="{{#(activePage === slug)}}active{{/(activePage === slug)}}">
        <a on-click="setActivePage" data-target="{{slug}}" href="#">{{text}}</a>
    </li>
    {{/menu}}
</ul>
</script>

<script id="pagesTemplate" type="text/ractive">
{{#posts}}
<section class="container post post-{{slug}}">
    <div class="row">
        <header>
            <h1 class="entry-title">{{title}}</h1>
        </header>
        <div class="entry-content">{{{content}}}</div>
    </div>
</section>
{{/posts}}
</script>

Ractiveオブジェクトを2つ作る

ractiveMenuオブジェクトにメニュー表示とページ切り替え機能
ractivePageオブジェクトにJSON取得、ページ更新機能をセットします
メニュー項目のプロパティは、WordPressのpageで投稿しときのslugと、メニューに表示してほしいテキストを設定します。

Javascript
var jsonUrl, ractivePage, ractiveMenu;

//ダミーURLです
jsonUrl = 'http://sample-wordpress.com/wp-json/posts';

ractiveMenu = new Ractive({
    el: '#main-menu',
    template: '#mainMenuTemplate',
    data: {

        //投稿したWordPressページのslugとメニューに表示したいテキスト
        //このプロパティ自体をWP REST APIからうまいこと取ってくれば自分で書かなくても済みます
        menu:[
            {"slug":"home","text":"ホーム"},
            {"slug":"about","text":"このサイトについて"},
            {"slug":"profile","text":"プロフィール"},
            {"slug":"contact","text":"お問い合わせ"}
        ]
    }
});
ractiveMenu.on({
    setActivePage: function (event) {
        this.set('activePage', event.node.getAttribute('data-target'));
    }
});

ractivePage = new Ractive({
    el: '#pages',
    template: '#pagesTemplate',
    data: {
        pages[];
    }
});
ractivePage.on({
    setPageData: function (pageName, keyPath) {
        var self = this,
          jqxhr = $.getJSON(
            jsonUrl,
            {
                //APIに投げるオブジェクト
                type: 'page',
                filter: {name: pageName}
            }
        );
        jqxhr.done(function (json) {

             //ページの内容を空にしてから取得した1件のページデータを追加
            self.set(keyPath, null) && self.set(keyPath, json[0]);

             //ここの処理をpushにするとページが下に追加される
            //self.push(keyPath, json[0]);
        })
        .fail(function () {
             //エラー処理
        })
        .always(function () {
        });
    }
});


//※修正点 ractiveMenuの{{activePage}}が更新されたらractivePageのページ更新イベントを発火
//ractiveMenu.observe()はractivePageをセットした後に書かないと動きませんでした
ractiveMenu.observe('activePage', function (val) {
     ractivePage.fire('setPageData', {type: 'page', name: val}, 'pages');
});


//最初に表示されるページを設定
//※修正点 activePageの値をセットするのみに変更
//=>ractiveMenu.observe('activePage')が作動する
ractiveMenu.set('activePage', 'home');


この例はページ表示のみですが、もちろん通常のカテゴリーpostなどもいけます。もう少し複雑になります。

WordPressのテンプレートタグからおさらばする

この先はもはや力技ですが、WordPressのテンプレート内で自らのJSONを取得してmustache.phpを使うと、Ractive.jsと同じテンプレートファイルを使ということができそうです。
これができれば静的htmlでもファーストビューは全く同じ内容を表示することができます。
例えば、template/menuTemplate.htmlにテンプレートの内容をmustacheで書いて、

<script id="menuTemplate" type="text/ractive">
    <?php require'template/menuTemplate.html';?>
</script>

などとするわけです。もちろんその場合、php側でも同じようなロジックを書かないといけません。
それにRactive.jsのmustacheは機能を少し拡張しているみたいなので、まったくそのままというわけにもいかなそうですが。

WordPressのテンプレートタグからおさらばする(なぜ?)日も近いです。

追記:上記の野望についてはいったんあきらめました。実際やってみて、ある程度は実現できたのですが、Ractive用に書いたテンプレートをそのまま本家mustacheに適用しようとすると当然互換性が保てず、かといって Ractive側で拡張している機能は便利すぎて手放すわけにもいかず、とりあえずphpコメントアウトする、とか力技でなんとかしましたが、無駄な労力がかかってしまいました。

もしやるとしたら、

  • php用にはシンプルなテンプレートを書いて、Ractive用にリッチなテンプレートを書く
  • そもそもこのプランはあきらめ、おとなしくWPのテンプレートタグを使う(ただしシンプルに書く)

としたほうが現実的だと思いました。