今回は仮に「name」というkeyが、「name_key」という変数に値として格納されているとしましょう。雰囲気的には次のような感じですが、当然次のコードは動きません。
{% set name_key = 'name' %} {% set offices = [ { name: '東京オフィス' }, { name: '札幌オフィス' } ] %} {%- for item in offices -%} {{ item.name_key }} {# この呼び出し方では当然動かない #} {%- endfor -%}
これは次のように書くことで、期待通りの出力を得ることが可能です(変数宣言は同じなので省略します)。
{%- for item in offices -%} {% set call_value = '{{ item.' + name_key + ' }}' %} {# 変数の呼び出しを文字列として組み立てる #} {{ call_value }} {# 文字列として組み立てた変数の呼び出しを展開する #} {%- endfor -%}
ここまでの解説ではただ単に非現実的で、使いどころのないコードに思えます。この方法が必要になるのは、次のように「プロパティの数が可変なテーブル的構造のデータを、自動でで出力したい」という場合です。
次のデータを先ほどの方法を使用して、tableタグで出力してみます。
{%- for item in offices -%} {% set offices = { columns: { name: '支店名', address: '住所', tel: '電話番号' }, contents: [ { name: '東京オフィス', address: '東京都千代田区', tel: '03-XXXX-XXXX' }, { name: '札幌オフィス', address: '北海道札幌市', tel: '011-XXX-XXXX' } ] } %} <table> <tr> {# 1. 見出しの出力 #} {%- for val in offices.columns -%} <th>{{ val }}</th> {%- endfor -%} </tr> {# 2. contentsでループを回す #} {%- for item in offices.contents -%} <tr> {# 3. keyを取得するため、1.と同じようにループを回す #} {%- for key, val in offices.columns.items() -%} {# 4. 取得したkeyを使用して、contentsのデータを取り出す変数呼び出しを文字列として組み立てる #} {% set call_value = '{{ item.' + key + ' }}' %} {# 5. 4を展開する #} <td>{{ call_value }}</td> {%- endfor -%} </tr> {%- endfor -%} </table>出力結果
<table> <tr> <th>支店名</th> <th>住所</th> <th>電話番号</th> </tr> <tr> <td>東京オフィス</td> <td>東京都千代田区</td> <td>03-XXXX-XXXX</td> </tr> <tr> <td>札幌オフィス</td> <td>北海道札幌市</td> <td>011-XXX-XXXX</td> </tr> </table>
一気に複雑になってしまったので、順を追って解説します。
まずはcolumnsに格納されている各valueを見出しとして出力します。columnsはディクショナリですが、普通にループを回すとvalue値が取得できます。
次に、contentsの要素ごとにループを回します。これ自体は特に特別なコードではありません。
contents内の各ディクショナリのvalueにアクセスするため、columnsの各キーを取得する必要があります。for文をこのように記述するとディクショナリのkeyにもアクセスできるようになり、これはHubSpot CMSの公式ドキュメントにも紹介されている方法です。
本記事で紹介するメインのコードです。先ほどの「基本形」セクションのコードと本質的に同じです。
こちらも本記事で紹介するメインのコードで、「基本形」セクションのコードと本質的に同じです。
この状態であれば、次のようにコンテンツが増えても、HTMLの出力をしている側のコードは一切修正する必要がありませんので、つまりデータと出力を疎結合に保てている証となります。
{% set offices = { columns: { name: '支店名', address: '住所', tel: '電話番号', staff_num: 'スタッフ数' {# 追加 #} }, contents: [ { name: '東京オフィス', address: '東京都千代田区', tel: '03-XXXX-XXXX', staff_num: '10名' {# 追加 #} }, { name: '札幌オフィス', address: '北海道札幌市', tel: '011-XXX-XXXX', staff_num: '3名' {# 追加 #} } ] } %} {# 出力の方のコードには一切変更なし #}出力結果
<table> <tr> <th>支店名</th> <th>住所</th> <th>電話番号</th> <th>スタッフ数</th> </tr> <tr> <td>東京オフィス</td> <td>東京都千代田区</td> <td>03-XXXX-XXXX</td> <td>10名</td> </tr> <tr> <td>札幌オフィス</td> <td>北海道札幌市</td> <td>011-XXX-XXXX</td> <td>3名</td> </tr> </table>
この方法が何より真価を発揮するのは、カスタムモジュール内でHubDBテーブルを選択できるようにしている場合です。これについては基本形のHubDB記事にて、実例を紹介しています。
以上、変数の値を他の変数の呼び出しに使う方法をご紹介しました。この方法をとることによってデータと出力の疎結合性を高められるため、コード設計としても出来ることがかなり広がると思います。
しかし公式ドキュメントで紹介されている方法ではなく、ハックの域を出ないものですので、使用の際は万が一のことを考え、影響範囲が広くなりすぎないようにすることをオススメします。