カテゴリと記事を混在したツリー形式での出力

MTQに、以下のような質問がありました。

階層順に「トップレベルカテゴリ→サブカテゴリ→個別記事」の様な記事一覧を作りたいです。

この質問に答えます。

1.質問の概要

以下の図のように、カテゴリと記事を混在して、ツリー形式で出力したいとのことです。

├ 親カテゴリ1
│ ├ 子カテゴリ1-1
│ │ ├ 記事1-1-1
│ │ ├ 記事1-1-2
│ │ ...
│ │ └ 記事1-1-x
│ ├ 子カテゴリ1-2
│ │ ├ 記事1-2-1
│ │ ├ 記事1-2-2
│ │ ...
│ │ └ 記事1-2-x
│ ...
│ ├ 子カテゴリ1-x
│ │ ├ 記事1-2-1
│ │ ├ 記事1-2-2
│ │ ...
│ │ └ 記事1-2-x
│ ├ 記事1-1
│ ├ 記事1-2
│ ...
│ └ 記事1-x
├ 親カテゴリ2
...

2.テンプレートの組み方

上記のような出力を得るには、以下のようにテンプレートを組みます。

<mt:TopLevelCategories>
  <mt:SubCatIsFirst>
    <ul>
  </mt:SubCatIsFirst>
  <li><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
  <mt:HasSubCategories>
    <$mt:SubCatsRecurse$>
  <mt:Else>
    <mt:Entries>
      <mt:EntriesHeader><ul></mt:EntriesHeader>
      <li><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></li>
      <mt:EntriesFooter></ul></mt:EntriesFooter>
    </mt:Entries>
  </mt:HasSubCategories>
  </li>
  <mt:SubCatIsLast>
    <mt:Entries>
      <li><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></li>
    </mt:Entries>
    </ul>
  </mt:SubCatIsLast>
</mt:TopLevelCategories>

考え方は以下の通りです。

2-1.カテゴリの一覧のツリー出力

まず、カテゴリ一覧だけをツリー出力します。
この考え方は、以下の記事が分かりやすいので、ご参照ください。

MTSubCatsRecurse タグの苦手意識を克服したいあなたへ(かたつむりくんのWWW)

2-2.下の階層がないカテゴリの記事の出力

次に、あるカテゴリについて、以下のように出力を分けます。

  • そのカテゴリの下の階層にカテゴリがあれば、下の階層のツリーを出力します。
  • そのカテゴリの下の階層にカテゴリがなければ、そのカテゴリの記事一覧を出力します。

上の図で言うと、親1カテゴリには子カテゴリがあるので、親1カテゴリを出力した後には、その下の階層のツリーを出力します。
一方、子カテゴリ1-1には子カテゴリがないので、子カテゴリ1を出力した後には、そのカテゴリの記事一覧(記事1-1-1など)出力します。

まず、「そのカテゴリの下の階層にカテゴリがある」かどうかで処理を分けます。
これはMTHasSubCategoriesタグで行うことができます(リストの6行目)。

また、「そのカテゴリの下の階層にカテゴリがあれば、下の階層のツリーを出力」は、MTSubCatsRecurseタグ1つで行うことができます(リストの7行目)。

一方、「そのカテゴリの下の階層にカテゴリがない」場合は、MTHasSubCategoriesタグの条件を満たさないので、リストの9~12行目に処理が進み、そのカテゴリの記事一覧が出力されます。

2-3.カテゴリのリストの後に記事を出力

次に、あるカテゴリの下の階層のカテゴリすべて出力した後に、そのカテゴリの記事の一覧を出力します。
上の図で言うと、親1カテゴリの下の階層のカテゴリ(子1-1~子1-xカテゴリ)をすべて出力した後に、親1カテゴリの記事(記事1-1~記事1-x)を出力します。

下の階層のカテゴリをすべて出力したかどうかは、MTSubCatIsLastタグで判断できます(リストの16行目)。
そこで、MTSubCatIsLastタグのブロックの中に、MTEntriesタグのブロックを入れます(リストの17~19行目)。

3.問題点

上であげたテンプレートでは、どのカテゴリにも属さない記事は出力されません。

本来なら、どのカテゴリにも属さない記事は、トップレベルのカテゴリのリストの後に出力したいです。
しかし、Movable Typeの標準機能では、どのカテゴリにも属さない記事を直接的に出力できるテンプレートタグがありません。
そこで、この処理は割愛しました。