たとえば、製品情報をMTのブログ記事で管理していて、カテゴリで製品の「分類」や「事業部」などを保持している場合に、ブログ記事アーカイブ中でその製品を管轄する「事業部」を表示したくなったときなど。(えらく具体的な例だ)
カスタムフィールドで保持していれば表示は簡単だが、「事業部」ごとにアーカイブを書き出したいときなどはこの方法が楽なのである。
- 事業部
- 事業部A
- 事業部B
- 事業部C
- 分類
- 分類A
- 分類B
- 分類B1
- 分類B2
- 分類C
子カテゴリを表示したいとき
事業部A かつ 分類B1 に属する製品情報があったとしよう。
製品がどの事業部に属するかを表示したくなったとき、MTEntryCategoriesでは分類も出てしまうのでうまくいかない。列挙してMTIfで逐一判定なんてのはありえない。
すこし処理コストが気になるけど、MTIfのlikeを使ってこんな感じでできる。
<mt:SetVarBlock name="entry_category_ids">,<mt:EntryCategories glue=","><mt:CategoryID></mt:EntryCategories>,</mt:SetVarBlock>
<mt:SubCategories category="事業部">
<mt:SetVarBlock name="matcher"><$MTCategoryID$></mt:SetVarBlock>
<mt:If name="entry_category_ids" like="$matcher">
<$MTCategoryLabel escape="html"$>
</mt:If>
</mt:SubCategories>
まず記事に設定されたカテゴリのIDを連結して、検索用の文字列をつくり、変数entry_category_ids
に入れておく。生成された文字列は「,1,2,3,」のように、どのIDの前後にも「,」が付いていて、たとえば「,1,」のような文字列で検索できるようになっている。glueだけだと、先頭と終端のIDについて「,」が足りないので検索できない。(「,」をつけて検索しないと、たとえば「1」が「10」にマッチしてしまう)
つぎに、MTSubCategoriesで「事業部」のサブカテゴリを回しつつ、entry_category_ids
にIDが含まれるカテゴリを探す。
みつかれば、それが製品に設定された「事業部」というわけだ。
子孫カテゴリを表示したいとき
上記の方法では、製品に設定された分類を表示するには、うまくいかない。
製品に設定された「分類B1」は「分類」の直接の子ではなく、子の子、つまり孫なので、SubCategoriesでは出てこないからだ。
単純に MTSubCategories をネストさせたのでは、たとえばもう1階層増えてひ孫が設定された場合に破綻してしまう。それでいちいちテンプレート修正とか、ダサいよね。
こういうときは再帰を使うのが簡単だ。上記のコードを少し手直しして...
<mt:SetVarBlock name="entry_category_ids">,<mt:EntryCategories glue=","><mt:CategoryID></mt:EntryCategories>,</mt:SetVarBlock>
<mt:SetVarTemplate name="category_loop_tmpl">
<mt:SetVarBlock name="matcher"><$MTCategoryID$></mt:SetVarBlock>
<mt:If name="entry_category_ids" like="$matcher">
<$MTCategoryLabel escape="html"$>
</mt:If>
<mt:HasSubCategories>
<mt:SubCategories>
<$MTVar name="category_loop_tmpl"$>
</mt:SubCategories>
</mt:HasSubCategories>
</mt:SetVarTemplate>
<mt:SubCategories category="分類">
<$MTVar name="category_loop_tmpl"$>
</mt:SubCategories>
category_loop_tmpl
を再帰関数的に使うことで、繰り返しIDのチェックと、子孫へのコンテキストスイッチを実現できる。これなら、たとえカテゴリの階層に関係ない。
ただし、こういうのがテンプレート中に散在すると非常に見づらいので、なるべくテンプレートモジュールに切り出すとかして見通しをよくするのがよいと思う。キャッシュが使えるしね。