連想配列(ハッシュ)や条件分岐を駆使して同じタグの付いたエントリーをリストアップ

2008-07-15
9分で読了
更新: 2025-12-14

目次

relatedtags.gif
(完成図)

MTSetVar(Block)/MTIfタグの具体的な利用例。 (Junnama Online (Mirror))さんの記事を参考に、現に表示されているエントリーに付いているタグと同じタグが付いているエントリーをリストアップするテンプレートを書いてみました。

ただ同じタグが付いているエントリーを並べただけでは面白くないので、「関連性の高さで2つにグルーピングして表示」するようにしてみました。

ソースコード

まずは完成したソースコードを紹介します。



<$mt:TagName$>
<$mt:TagName$>
<$mt:TagName$>
<$mt:EntryID pad="1"$>


 <$mt:EntryID pad="1"$>
 <$mt:EntriesCount$>
 
 
 <$mt:EntryTitle$>
 
 



 <$mt:EntryID pad="1"$>
 <$mt:EntriesCount$>
 <$mt:SetVar name="already" value="0"$>
 
 
 
 
 
 <$mt:SetVar name="already" value="1"$>
 
 
 
 <$mt:EntryTitle$>
 
 
 
 


<$mt:GetVar name="count(listDate)"$>
<$mt:GetVar name="count(listDate_any)"$>


 
[関連エントリー]
タグ:<$mt:GetVar name="thisTags"$> をすべて含む
  • <$mt:GetVar name="__value__"$>
タグ:<$mt:GetVar name="thisTags"$> のいずれかを含む
  • <$mt:GetVar name="__value__"$>
[関連エントリー]
  • <$mt:GetVar name="__value__"$>

Movable Type の変数、配列、条件分岐を駆使しました。結果、参考にしたJunnama Online (Mirror) さんのソースとはちょっと変わっていますし、長くなってしまいました。

以下で順を追って解説してみます。

解説

全体的な設定



<$mt:TagName$>
<$mt:TagName$>
<$mt:TagName$>
<$mt:EntryID pad="1"$>

MTEntryIfTagged は、記事にタグを付けているときだけ囲まれた内容を処理します。

MTSetVarBlock によって変数を定義しています。定義している内容はそれぞれ次のとおりです。

allTags

現在表示しているエントリーに付いているすべてのタグを、「AND」でつなげて変数 allTags に代入。
例:タグ1 AND タグ2

anyTags

現在表示しているエントリーに付いているすべてのタグを、「OR」でつなげて変数 anyTagsに代入。
例:タグ1 OR タグ2

thisTags

現在表示しているエントリーに付いているすべてのタグを、「,」でつなげて変数 thisTagsに代入。
例:タグ1 , タグ2

thisID

現在表示しているエントリーの ID を pad モディファイアを指定して常に6桁で変数 thisID に代入。6桁にした方が、ソートがうまくいったので。

現在表示されているエントリーに付いている「すべてのタグ」を含むエントリーのリストアップ


 <$mt:EntryID pad="1"$>
 <$mt:EntriesCount$>
 
 
 <$mt:EntryTitle$>
 
 

まず で、現在表示しているエントリーに付いている「すべてのタグ」を含むエントリーを、最大11件リストアップします。

最大10件ではなく最大11件となっているのは、リストアップされるエントリーには必ず現在表示されているエントリーを含むので、そのエントリーをリストから除いたときにリストアップされるエントリー数が一つ減ってしまうからです。

その次の SetVarBlock タグで、以下の二つの変数を定義しています。

listID
リストアップされるたびにそのエントリーの ID を代入。
listCount
リストアップされるエントリーの件数を代入。

その後、もしリストアップされるエントリーの件数( listCount )が1より大きい場合( if タグ)で、かつ、リストアップされるエントリーの ID が、現在表示されているエントリーの ID と異なる場合( Unless タグ)に次の内容を処理します。

ここが今回のテンプレートの肝で、上記の条件を満たしたエントリーを変数 listDate に次のような連想配列(ハッシュ)として代入します。

連想配列 listDate
  • キー: リストアップされるエントリー ID
  • 値: リストアップされるエントリーへのリンク

ここで直接エントリーへのリンクを出力せずに連想配列に代入する形をとったのは、後ほど (X)HTML を出力するときに、ここでリストアップされた件数で条件分岐を行いたかったためです。

現在表示されているエントリーに付いている「いずれかのタグ」を含むエントリーのリストアップ


 <$mt:EntryID pad="1"$>
 <$mt:EntriesCount$>
 <$mt:SetVar name="already" value="0"$>
 
 
 
 
 
 <$mt:SetVar name="already" value="1"$>
 
 
 
 <$mt:EntryTitle$>
 
 
 
 

まず、現在表示しているエントリーに付いている「いずれかのタグ」を含むエントリーを、最大11件リストアップする設定にし、変数を三つ定義します。

listID_any
リストアップされるたびにそのエントリーの ID を代入。
listCount_any
リストアップされるエントリーの件数を代入。
already
0 を代入(初期化)。

続いて、三つの条件分岐が入れ子になります。

  • 「いずれかのタグ」を含むエントリー数( listCount_any )が、「すべてのタグ」を含むエントリー数( listCount )より多い場合( if )で、
  • かつ、「いずれかのタグ」を含むエントリー数( listCount_any )が 1 よりも大きくて( if )、
  • かつ、リストアップされるエントリーの ID が、現在表示されているエントリーの ID と異なる場合( Unless )

この三つの条件分岐を満たす場合のみ、次の内容を処理します。


 
 <$mt:SetVar name="already" value="1"$>
 


 <$mt:EntryTitle$>

ここでは、まず Loop タグで配列変数 listDate に格納されたデータについて繰り返し処理をします。

処理する内容は、ここでリストアップされる「いずれかのタグ」を含むエントリーの ID ( listDate_any )が、「すべてのタグ」を含むエントリーとしてリストアップされた ID ( listDate の $__key__ )の中にすでに含まれているかどうかをチェックし、含まれているならば変数 already に 1 を代入します。

ループで、ID のチェックが終わり、「すべてのタグ」を含むとしてリストアップされていなければ 変数 already は初期化した 0 のままです。

したがって、次のUnless タグで、「もし変数 already が 1 でなければ」、つまり「いずれかのタグ」を含むとして初めてリストアップされたエントリーについてのデータのみ、変数 listDate_any に以下のような連想配列(ハッシュ)として代入します。

連想配列 listDate_any
  • キー: リストアップされるエントリー ID
  • 値: リストアップされるエントリーへのリンク

(x)HTML を出力する

<$mt:GetVar name="count(listDate)"$>
<$mt:GetVar name="count(listDate_any)"$>

まずは、次の二つの変数を定義します。

listDateCount
「すべてのタグ」を含むとしてリストアップされたエントリーの数を代入。
listDateCount_any
「いずれかのタグ」を含むとしてリストアップされたエントリーの数を代入。

続いて、(x)HTML を出力します。


 
[関連エントリー]
タグ:<$mt:GetVar name="thisTags"$> をすべて含む
  • <$mt:GetVar name="__value__"$>
タグ:<$mt:GetVar name="thisTags"$> のいずれかを含む
  • <$mt:GetVar name="__value__"$>
[関連エントリー]
  • <$mt:GetVar name="__value__"$>

全体的な条件分岐イメージは次のようになります。

[すべてのタグを含む・いずれかのタグを含むエントリーが両方ある場合]

[関連エントリー]
タグ:タグ1,タグ2 をすべて含む
  • エントリーへのリンク
タグ:タグ1,タグ2 のいずれかを含む
  • エントリーへのリンク
[すべてのタグを含む・いずれかのタグを含むエントリーのどちらかがある場合]

[関連エントリー]
  • エントリーへのリンク

このように、エントリーがリストアップされたか否かを条件として分岐するために、先ほどエントリーをリストアップさせた際に、直接エントリーへのリンクを出力せずに連想配列に代入する形をとったわけです。

エントリーへのリンクは、次のように Loop タグを使って、その配列の値を取り出しています。


 
  • <$mt:GetVar name="__value__"$>
  • 説明をコメントとして入れたソースコード

    最後に、簡単な説明をコメントとして入れたソースコードを載せておきます。

    
    
    
    
    
    <$mt:TagName$>
    
    
    <$mt:TagName$>
    
    
    <$mt:TagName$>
    
    
    <$mt:EntryID pad="1"$>
    
    
    
    
    
    
     
     <$mt:EntryID pad="1"$>
    
     
     <$mt:EntriesCount$>
    
     
     
    
     
     
     
     <$mt:EntryTitle$>
     
    
     
    
    
    
    
    
    
    
    
     
     <$mt:EntryID pad="1"$>
    
     
     <$mt:EntriesCount$>
    
     
     <$mt:SetVar name="already" value="0"$>
    
     
     
    
     
     
    
     
     
    
     
     
     
     
     <$mt:SetVar name="already" value="1"$>
     
     
    
     
     
     
     <$mt:EntryTitle$>
     
    
     
    
     
    
     
    
    
    
    
    
    
    
    <$mt:GetVar name="count(listDate)"$>
    <$mt:GetVar name="count(listDate_any)"$>
    
    
    
    
    
    [関連エントリー]
    タグ:<$mt:GetVar name="thisTags"$> をすべて含む
    • <$mt:GetVar name="__value__"$>
    タグ:<$mt:GetVar name="thisTags"$> のいずれかを含む
    • <$mt:GetVar name="__value__"$>
    [関連エントリー]
    • <$mt:GetVar name="__value__"$>

    もし間違っている箇所があればご指摘いただけると嬉しいです。

    万が一、「おーコレいいじゃん、コピペして使おう」って思う方がいたときのために、タブでインデントしたファイルも置いておきます。

    Movable Type の公式サイトには、テンプレートタグリファレンスが掲載されていますが、使い勝手がいいとは言えません。同じような感想をお持ちの方は以下の書籍がお勧めです。

    そのうち感想をアップしますが、かなり便利です。

    この記事をシェア

    関連記事