MTTopLevelCategoriesタグで記事がないカテゴリを出力しない(その2)

昨日の記事の続きで、MTTopLevelCategoriesタグを使う際に、記事がないカテゴリを出力しない方法を解説します。

1.子カテゴリにも記事が全くない場合の問題

昨日の記事のテンプレートで、たいていの場合は問題なく動作します。
しかし、問題が起きる場合もあります。

以下のようなカテゴリの状況を考えてみてください(カテゴリ名の後のカッコ内の数字は、そのカテゴリにある記事の数)。

├ 親1(0)
│ ├ 子1-1(0)
│ └ 子1-2(0)
├ 親2(5)
...

この場合、親1カテゴリには記事はありませんが、子カテゴリがあります。
そのため、昨日の記事での条件を満たしますので、親1カテゴリは出力されます。
一方、子1-1や子1-2には記事はなく、かつ子カテゴリもないので、出力されません。
結果として、以下のようなツリー構造が出力され、親1カテゴリが残る形になります。

├ 親1(0)
├ 親2(5)
...

2.配下のカテゴリに記事があるかどうかを調べる

ここまでの話から、あるカテゴリの配下に子(子孫)カテゴリがある場合、配下のカテゴリの記事があるときだけ、そのカテゴリを出力するようにします。
前述の例だと、親1カテゴリの配下のカテゴリには記事がないので、親1カテゴリは出力されなくなります。

あるカテゴリの配下に記事があるかどうかを調べるには、MTSubCategoriesタグで配下のカテゴリを順に回り、それぞれのカテゴリの記事の数を合計します。
合計が1以上なら、配下のどこかのカテゴリに記事があることになりますので、それを条件にします。

3.テンプレートの例

ここまでの話に基づいてテンプレートを組むと、以下のようになります。

<mt:TopLevelCategories>
  <mt:SubCatIsFirst><ul></mt:SubCatIsFirst>
  <$mt:SetVar name="flag" value="0"$>
  <mt:If tag="CategoryCount">
    <$mt:SetVar name="flag" value="1"$>
  <mt:Else>
    <mt:HasSubCategories>
      <$mt:SetVar name="count" value="0"$>
      <mt:SubCategories>
        <$mt:CategoryCount setvar="count_a"$>
        <$mt:SetVar name="count" op="+" value="$count_a"$>
        <$mt:SubCatsRecurse$>
      </mt:SubCategories>
      <mt:If name="count">
        <$mt:SetVar name="flag" value="1"$>
      </mt:If>
    </mt:HasSubCategories>
  </mt:If>
  <mt:If name="flag">
    <li><$mt:CategoryLabel$>(<$mt:CategoryCount$>)
    <$mt:SubCatsRecurse$>
    </li>
  </mt:If>
  <mt:SubCatIsLast></ul></mt:SubCatIsLast>
</mt:TopLevelCategories>

8~16行目が、昨日のテンプレートとは異なる点です。
昨日のテンプレートでは、子カテゴリがあれば(MTHasSubCategoriesタグ)、即座に変数$flagに1を代入していました。
一方、今日のテンプレートでは、以下の手順で変数$flagに値を代入します。

  • 子カテゴリがあるかどうかを調べます(7/17行目)。
  • 子カテゴリがあれば、まず変数$countの値を0にします(8行目)。この変数に、子カテゴリの記事数の合計を求めます。
  • 子カテゴリを順に回ります(9/12/13行目)
  • 各子カテゴリの記事の数を変数$countに足していきます(10/11行目)。
  • 変数$countの値が1以上なら、変数$flagに1を代入します(14~16行目)。

4.パフォーマンスの問題

ここまでで、正しい出力を得ることができます。
ただ、子カテゴリを何度も回って記事数を数えることから、パフォーマンスの問題が生じます。
パフォーマンスが重要な場合は、プラグインを作って最適なロジックを組む必要があります。