カテゴリリスト内での特定のカテゴリとその親の判断

MTQに、「カテゴリ一覧(メニュー)について」という質問があがっていました。
この質問に答えてみます。

1.カテゴリとその親の取得

ご質問の事例を実現するには、現在処理中のカテゴリと、その親のカテゴリとを、判断することが必要になります。
現在処理中のカテゴリについて、その一番上の親から、順に階層を下って、各階層のカテゴリを得るには、MTParentCategoriesタグを使います。

ご質問の例では、「現在処理中のカテゴリと、その親のカテゴリに、カレントを示すマークをつけたい」ということです。
そこで、ハッシュを使って、それらのカテゴリに印をつけるようにします。

ハッシュに「current_cat_ids」という名前を付けるとすると、この処理は以下のように書くことができます。

<mt:ParentCategories>
  <$mt:CategoryID setvar="cat_id"$>
  <$mt:SetVar name="current_cat_ids" key="$cat_id" value="1"$>
</mt:ParentCategories>

例えば、現在処理中のカテゴリのIDが5番で、その親カテゴリのIDが3番だとします。
この場合、上記の処理によって、ハッシュcurrent_cat_idsの内容は以下のようになります。

キー(カテゴリのID)値(印)
51
31

2.カテゴリアーカイブのアドレスを変数に代入

現在処理中のカテゴリが子カテゴリである時には、子カテゴリのリンク先だけでなく、親カテゴリのリンク先も子カテゴリにしたいということです。
このようなことを行うには、現在処理中の子カテゴリのアドレスを、前もって変数に代入しておくと良いです。
そして、親カテゴリを出力する際に、そのリンク先を、上で設定した変数にします。

カテゴリのアドレスを変数cat_archive_linkに代入するなら、以下のように書きます。

<$mt:CategoryArchiveLink setvar="cat_archive_link"$>

3.ブログ記事の主カテゴリの取得

カテゴリアーカイブテンプレートの中では、1.および2.のようにテンプレートに書けば、希望通りの動作になります。
しかし、ブログ記事アーカイブテンプレートの中では、ブログ記事が複数のカテゴリに属していることもあり得るので、ブログ記事の主カテゴリに限定して処理を行うようにします。

ブログ記事の主カテゴリを得るには、MTEntryPrimaryCategoryタグ(ブロックタグ)を使います。
1.および2.の部分を、MTEntryPrimaryCategoryタグのブロックで囲みます。

4.カテゴリリスト出力中のカレントの判断

現在処理中のカテゴリだけでなく、その親のカテゴリも、カレントと判断したいということです。

1.の手順で、カレントとみなすカテゴリのIDを、ハッシュcurrent_cat_idsに代入しています。
そこで、以下のようにテンプレートを組んで、カレントとみなすカテゴリかどうかを判断するようにします。

<mt:TopLevelCategories>
  <$mt:CategoryID setvar="cat_id"$>
  ...
  <mt:If name="current_cat_ids" key="$cat_id" eq="1">
    カレントとみなすカテゴリの場合に出力する内容
  <mt:Else>
    それ以外のカテゴリの場合に出力する内容
  </mt:If>
  ...
</mt:TopLevelCategories>

2行目で、カテゴリのIDを変数cat_idに代入します。
そして、4行目のMTIfタグで、カレントのカテゴリを表すハッシュ(current_cat_ids)の中で、キーが変数cat_idの値になっている要素を調べて、その値が1になっているかどうかを判断します。

1.の処理によって、カレントとみなすカテゴリでは、ハッシュcurrent_cat_idsの要素の値が1になっています。
例えば、現在出力中のカテゴリのIDが5番で、その親のカテゴリのIDが3番だとします。
この場合、ハッシュcurrent_cat_idsの内容は、1.に示した表のようになっています。
また、現在出力中のカテゴリのIDが5なので、2行目の文によって、変数cat_idの値は5になります。
したがって、4行目のMTIfタグは、ハッシュの中でキーが5になっている要素を見て、その値が1になっているかどうかを調べることになります。
そのため、MTIfタグの条件が成立して、5行目(カレントとみなすカテゴリの場合に出力する内容)に進みます。

5.テンプレートの例

ここまでの話に沿って、質問のようなことを実現するテンプレートを組みます。

5-1.カテゴリアーカイブテンプレート

カテゴリアーカイブテンプレートには、以下のような部分を入れます。

<mt:ParentCategories>
  <$mt:CategoryID setvar="cat_id"$>
  <$mt:SetVar name="current_cat_ids" key="$cat_id" value="1"$>
</mt:ParentCategories>
<$mt:CategoryArchiveLink setvar="cat_archive_link"$>
<mt:TopLevelCategories>
  <$mt:CategoryID setvar="cat_id"$>
  <mt:SubCatIsFirst><ul></mt:SubCatIsFirst>
    <li>
    <mt:If name="current_cat_ids" key="$cat_id" eq="1">
      <a href="<$mt:GetVar name="cat_archive_link"$>"><$mt:CategoryLabel$></a>★
      <$mt:SubCatsRecurse$>
    <mt:Else>
      <mt:If tag="CategoryCount">
        <a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
      <mt:Else>
        <$mt:CategoryLabel$>
      </mt:If>
    </mt:If>
    </li>
  <mt:SubCatIsLast></ul></mt:SubCatIsLast>
</mt:TopLevelCategories>

1~4行目は、前述の1.の処理を行う部分です。
また、5行目で、前述の2.を行っています。

6行目以降で、カテゴリのリストを出力します。
10行目のMTIfタグで、出力しようとするカテゴリが、カレントとみなすカテゴリかどうかを判断します。
カレントであれば、11行目によってそのカテゴリの名前と、リンクが出力されます。
リンク先に変数cat_archive_linkを指定していますので、出力するカテゴリが親カテゴリであっても、子カテゴリにリンクするようになります。
また、カレントとみなすカテゴリであれば、その下の階層のカテゴリも出力するので、MTSubCatsRecurseタグで階層を下ります(12行目)。

一方、カレントでないカテゴリの場合は、そのカテゴリに記事がある(記事数が0でない)かどうかを判断して(14行目)、カテゴリ名の出力方法を変えます。

5-2.ブログ記事アーカイブテンプレート

ブログ記事アーカイブテンプレートでは、カテゴリアーカイブテンプレートの場合の1~5行目の部分を、以下のようにMTEntryPrimaryCategoryタグで囲みます。
それ以後の部分は、カテゴリアーカイブテンプレートの場合と同じです。

<mt:EntryPrimaryCategory>
  <mt:ParentCategories>
    <$mt:CategoryID setvar="cat_id"$>
    <$mt:SetVar name="current_cat_ids" key="$cat_id" value="1"$>
  </mt:ParentCategories>
  <$mt:CategoryArchiveLink setvar="cat_archive_link"$>
</mt:EntryPrimaryCategory>

6.変数(配列/ハッシュも含む)は必須

Movable Type 5.1 Webサイト製作ガイドVolume 2この例のように、手の込んだ処理をしようとすると、変数や、その応用である配列やハッシュを、避けて通ることができません。
拙著「Movable Type 5.1 Webサイト製作ガイドVolume 2」では、変数および配列/ハッシュについて、かなり詳しく解説しています。
「変数や配列/ハッシュがよく分からない」という方は、ぜひ拙著をお読みください。