オブジェクトをグループ分けして出力する(その2)

先日の「オブジェクトをグループ分けして出力する」の続きで、グループをカテゴリのように階層付ける方法を紹介します。

1.カスタムフィールドの定義

Movable Type標準のカスタムフィールドでは、カテゴリのような階層があるフィールドを作る機能はありません。
そこで、あまり良い方法ではありませんが、ドロップダウンを使って、個々の選択肢に階層の情報も含めるような仕組みを取ります。

たとえば、以下のようにグループを分けたいとします。

├ 赤
│ ├ 11
│ └ 12
└ 青
   ├ 21
  └ 22

この場合、ドロップダウンの選択肢を「赤_11,赤_12,青_21,青_22」にします。
そして、後でグループ分けする際に、フィールドの値を「_」で区切って、1階層目(赤/青)と2階層目(11/12/21/22)を得るようにします。

2.事例

先日のユーザーをグループに分けて出力する際のテンプレートを書き換えて、グループの1階層目が「赤」のユーザーを、2階層目で分けて出力する例を紹介します。

<mt:Authors need_entry="0">
  <$mt:AuthorGroup regex_replace="/^(.*)_(.*)$/","$1" setvar="group"$>
  <$mt:AuthorGroup regex_replace="/^(.*)_(.*)$/","$2" setvar="subgroup"$>
  <mt:If name="group" eq="赤">
    <$mt:SetVar name="groups" key="$subgroup" value="1"$>
    <mt:If name="subgroup">
      <mt:SetVarBlock name="$subgroup" function="push">
        <$mt:AuthorDisplayname$> <img src="<$MTAuthorUserpicURL$>" width="100" height="100" alt="" />
      </mt:SetVarBlock>
    </mt:If>
  </mt:If>
</mt:Authors>
<mt:Loop name="groups">
  <h1><$mt:GetVar name="__key__"$></h1>
  <ul>
  <mt:Loop name="$__key__">
    <li><$mt:GetVar name="__value__"$></li>
  </mt:Loop>
  </ul>
</mt:Loop>

前半(12行目まで)は、グループの1階層目が「赤」のユーザーを、2階層目で分ける処理です。
グループ名のカスタムフィールドのテンプレートタグ名を、MTAuthorGroupにしているものとします。

2行目と3行目は、正規表現を使って、「赤_11」等のグループ名を「_」で区切り、その前後を変数「group」と「subgroup」に代入する処理です。
「^(.*)_(.*)$」は、文字列を「先頭から『_』の前まで」と「『_』の後から最後まで」に区切り、メモリに記憶することを表す正規表現です。
また、「$1」と「$2」は、メモリに記憶した1つ目/2つ目の値を表します。

4行目のMTIfタグで、変数groupの値(=第1階層)が「赤」のときだけ、グループに分ける処理を行います。
5行目~11行目は、変数subgroupの値(=第2階層)で、ユーザーをグループに分ける処理です。

また、13行目以降は、グループごとにユーザーを出力する処理です。
この部分の内容は、前回の例とまったく同じです。

3.1階層目のグループごとに別々のページに分ける

2.の事例を含むインデックステンプレートを複数つくり、4行目の「<mt:If name="group" eq="赤">」の「赤」を「青」などに変えれば、1階層目のグループごとに、別々のページを出力することができます。
ただ、複数のテンプレートに同じような部分を何度も入力すると、後で修正する際に面倒です。
そこで、2.の事例の部分をテンプレートモジュールにしておいて、各インデックステンプレートにはそのテンプレートモジュールを組み込むようにすると良いです。

テンプレートモジュール側では、4行目のMTIfタグを書き換えて、第1階層のグループ名を変数で指定できるようにしておきます。
変数名を「out_group」にするなら、以下のように書き換えます。

<mt:If name="group" eq="$out_group">

そして、インデックステンプレート側では、MTIncludeタグでテンプレートモジュールを読み込む際に、変数に第1階層のグループ名を代入します。
それには、MTIncludeタグに「変数名="値"」のモディファイアを指定します。

たとえば、第1階層が「赤」のグループのページでは、インデックステンプレートのMTIncludeタグを以下のように書きます。

<$mt:Include module="テンプレートモジュール名" out_group="赤"$>