Json_2Tpl モジュールを使って専用モジュールを作ってみよう

a-blog cms ではビルドインモジュール(Entry_BodyやCategory_List...)と呼ばれる最初から入っているモジュールを使って動的にコンテンツを出力していきます。一般的なサイトを作るうえでは、ビルドインモジュールがあればそこまで困らないのですが、a-blog cmsで管理していないデータを出力したり、特殊な絞り込みをしたい場合は、PHPを書いて専用モジュールを開発する必要がありました。

そこで、Ver. 2.7.0 から導入される新しいビルドインモジュール Json_2Tpl を使う事でJSONさえ用意できれば、PHPを1行も書かずに思い通りのモジュールを作る事ができるようになります。

また、JSONがインターフェイスとなるので外部サービスとの連携もしやすくなります。

基礎編

まずは、モジュールIDの作成を行います。 管理ページ > モジュールID の モジュールID作成ボタン を押してモジュールIDを新規作成します。ここでは以下のような設定にしましょう。

  • モジュール: Json_2Tpl
  • id: sampleJson2Tpl
  • 名前: Json_2Tplの練習

モジュールID作成画面

モジュールID作成画面


出力をしたいJSONファイルを用意します。自分でJSONファイルを書く、外部サービスのJSONファイルを読む混むなどをするのですが、まずは練習用に以下のJSONファイルを使います。

http://ablogcms.io/sample.json

商品の一覧を出力しているJSONファイルです。これをa-blog cmsのテンプレートで出力してみましょう。

{
    "items": [
        {
            "id": "001",
            "name": "商品A",
            "color": "red",
    "size": ["S", "M", "L"],
            "price": {
                "tax_included": 108,
                "without_tax": 100
            }
        },
       ...
}

練習用のJSONファイルを、先ほど作成したモジュールIDに設定してみましょう。先ほど作成したモジュールIDの設定画面に移動します。表示設定のタブに移動して JSONファイル の入力欄に http://ablogcms.io/sample.json を入力しましょう。

Json_2Tplのモジュール設定には以下のものがあります。

  • キャッシュタイム: JSONファイルをキャッシュする時間を設定します。
  • JSONファイル: データもとであるJSONファイルを指定します。URLもしくはパスで指定できます。(Ver.2.7.7よりグローバル変数もパスの指定に利用できるようになりました)

Json_2TplモジュールID設定画面

Json_2TplモジュールID設定画面


モジュールの準備ができたので、実際にテンプレートに出力をしてみましょう。まずはモジュールブロックを書きます。 idは先ほど作成したモジュールIDのものを指定ください。

<!-- BEGIN_MODULE Json_2Tpl id="sampleJson2Tpl" -->
<h2>商品</h2>

<!-- END_MODULE Json_2Tpl -->

JSON

次に実際にデータを表示していくのですが、その前にJSONファイルについてちょっと学んでおきましょう。

JSONは 名前/値のペア の集まりで構成されています。: の前にあるのが名前です。また、{ } で囲まれている部分をオブジェクトと呼びます。様々なデータを持っているセットと考えていただければ大丈夫です。次に [ ] で囲まれている部分が配列になります。データを複数持つことができます。これらは互いに入れ子にする事ができるようになっています。

ではサンプルのデータを見ながら、どのようなデータになっているか見てみましょう。

{
    "items": [
        {
            "id": "001",
            "name": "商品A",
            "color": "red",
    "size": ["S", "M", "L"],
            "price": {
                "tax_included": 108,
                "without_tax": 100
            }
        },
       ...
}

まず、 items ですが、: のあとは [ になっていますので、Itemsは配列とわかります。配列の中身ですが、{ } で囲まれているのでオブジェクトを複数持っている事がわかります。

オブジェクトの中身ですが、id, name, color は文字列の値になっていますが、 price{ } で囲まれているのでオブジェクトです。そのオブジェクトの中身は 数値の値になっています。

JSON -> a-blog cmsテンプレート

これを踏まえてa-blog cmsのテンプレートを作っていきます。以下のようなルールがあります。

ここでのサンプルのコードは一部分を表示しているだけになります。全体のコード(動作するコード)は下のほうにあります。

配列の場合は、ループブロックで表現されます。ループブロックとは <!-- BEGIN 名前:loop --> という形のブロックになります。

ループブロックの中では、 glueブロック <!-- 名前:glue --> も利用できるようになります。glueブロックは ループ回数 - 1回 出力されるブロックになります。カンマで区切りたい場合などに利用すると便利です。

特殊な変数として {名前.i} という変数も利用できます。これは現在の配列番号を出力できます。

また配列の中身が、値の場合は(ここでゆうsize)配列の名前(ラベル)がそのまま変数名としても使えます。

<!-- BEGIN items:loop -->
{items.i}
<!-- BEGIN items:glue -->, <!-- END items:glue -->
...
<!-- END items:loop -->

<!-- BEGIN size:loop -->
<!-- BEGIN size:glue -->, <!-- END size:loop -->
{size.i} : {size}
<!-- END size:loop -->

名前(ラベル)がついたオブジェクト(例: "price": { ... })の場合は、ブロックで表現できます。ブロックとは <!-- BEGIN 名前 --> の形のブロックです。

<!-- BEGIN price -->
...
<!-- END price -->

名前(ラベル)のあとが値の場合、変数として出力できます。変数は {名前} で表現されます。 もちろんこの変数には校正オプションも利用できます。

{id}
{name}
{color}
{tax_included}[number_format]
など
  • 配列 -> ループブロック(例 <!-- BEGIN items:loop -->)
  • 名前(ラベル)がついたオブジェクト -> ブロック(例: <!-- BEGIN price -->)
  • 名前(ラベル)のあとが配列でもオブジェクトでもない値 -> 変数(例: {color})

取得したJSONのルートが配列だった場合

これまでの説明・サンプルは、取得先のJSONのルート(最上位)がオブジェクトである前提でした(items キーを持つサンプルJSON自体がオブジェクトルートです)。

[
  { "name": "foo" },
  { "name": "bar" }
]

このような配列がルートの場合は自動的にひとまとめにされ、...のようなループブロックとして展開されます。

一方、これまでの例のように、取得先のJSONのルートがオブジェクトだった場合は、このループ化は行われません。

{ "name": "foo", "value": 1 }

この場合、root:loopのようなブロックは作られず、namevalueが上記の変換ルール(配列→ループブロック、名前付きオブジェクト→ブロック、それ以外の値→変数)に従って、そのままトップレベルの変数・ブロックとして展開されます({name} {value})。

{"items": [...], "total": 5} のように、配列がオブジェクトの中の1つのキーに入っている場合も同様です。ルート自体はオブジェクトなのでループ化されず、items キーがこのページの変換ルールに従ってブロック化されます(値が配列なので items:loop のようなループブロックになります)。total は変数になります。

JSONの構造の一部(例: items だけ)を指定して取り出す設定はありません。展開された結果をテンプレート側で参照してください。

Twigベース(V2)モジュールの場合

V2モジュール(Twigテンプレート)を使用している場合は、上記のような自動判定・自動ループ化は行われません。取得したJSONはそのまま data 変数に入るので、ルートが配列かオブジェクトかに応じてテンプレート側で明示的に書き分けてください。

{# JSONのルートが配列の場合 #}
{% for item in data %}
  {{ item.name }}
{% endfor %}

{# JSONのルートがオブジェクトの場合 #}
{{ data.name }}

では以上のルールにしたがって練習用JSONのすべての値を出力してみましょう。以下のようなテンプレートになれば正解です。

<!-- BEGIN_MODULE Json_2Tpl id="sampleJson2Tpl" -->
<h2>商品</h2>
<ul>
    <!-- BEGIN items:loop -->
    <li>
        {items.i}: {id}: {name}<br>
        color: {color}<br>
        size: <!-- BEGIN size:loop --><!-- BEGIN size:glue -->, <!-- END size:glue -->{size}<!-- END size:loop --><br>
        <!-- BEGIN price -->
            税込: {tax_included}円
            税別: {without_tax}円
        <!-- END price -->
    </li>
    <!-- END items:loop -->
</ul>
<!-- END_MODULE Json_2Tpl -->

表示結果

表示結果


取得先URLに関する制限(Ver. 3.2.29, Ver. 3.1.75, Ver. 3.0.61 以降)

Ver. 3.2.29(および Ver. 3.1.75, Ver. 3.0.61)以降、Json2tplモジュールで取得先に指定するURLについて、以下の制限がデフォルトで適用されます。

  • 社内ネットワークやプライベートIPアドレス宛のURLは取得できません

  • ローカルファイルの参照は、テーマディレクトリ配下に限定されます

  • レスポンスの Content-Type は JSON・プレーンテキスト系のみ許可されます(それ以外は取得できません)

  • レスポンスサイズの上限(デフォルト5MB)、リダイレクト回数の上限(デフォルト5回)が設けられています

社内システムのAPIやテーマ外のローカルファイルを取得先に指定している場合、これらの制限により取得できなくなることがあります。その場合は、a-blog cms 設置ディレクトリ直下の環境設定ファイル(.env)に以下の設定を追記して明示的に許可してください。

SON2TPL_SSRF_WHITE_LIST=10.0.1.0/24,192.168.1.100   # 許可するプライベートIP・CIDRをカンマ区切りで指定
JSON2TPL_LOCAL_WHITE_LIST=storage/,/var/www/shared-data # 許可するローカルディレクトリをカンマ区切りで指定(テーマ配下は常に許可)
JSON2TPL_MAX_CONTENT_LENGTH=5242880   # レスポンスサイズの上限(バイト)。既定は5MB
JSON2TPL_MAX_REDIRECTS=5              # リダイレクト追跡回数の上限