ブログ記事のページに関連記事を出力する

MTQで以下のような質問を見かけました。

  • ブログ記事に関連記事を表示したいです。
  • ブログ記事にタグを付けているときは、同じタグを持つ記事の中から最新の5件を読み込み、タイトルの一覧を表示します。
    たとえば、ブログ記事に「赤」「青」「黄色」のタグを付けている場合、「赤」か「青」か「黄色」のタグが付いている記事の中から、最新の5件を読み込みます。
  • ブログ記事にタグを付けていない場合は、同じカテゴリに属する記事を読み込み、タイトルの一覧を表示します。

この質問に答えます。

1.タグが付いているかどうかで処理を分ける

まず、ご質問の例では、ブログ記事にタグが付いているかどうかで処理を分ける必要があります。
この判断は、MTEntryIfTaggedタグで行うことができます。

ご質問の例の場合だと、以下のような流れでテンプレートを組んでいきます。

<mt:EntryIfTagged>
  同じタグを持つブログ記事最新5件のリストを出力する部分
<mt:Else>
  同じカテゴリに属するブログ記事最新5件のリストを出力する部分
</mt:EntryIfTagged>

2.自分自身を除く最新5件のブログ記事を出力する

MTEntriesタグに「lastn="○"」のモディファイアを指定すれば、最新○件のブログ記事を出力することができます。
たとえば、「lastn="5"」とすれば、最新5件のブログ記事を出力することができます。
しかし、ブログ記事テンプレートの中で最新記事を出力する際に、「出力中のブログ記事自身を除いて○件を出力する」という機能はありません。

そこで、MTEntriesタグでは、lastnモディファイアの値を1増やして、1件余分にブログ記事を読み込みます。
今取り上げている例だと、「lastn="6"」とします。
そして、MTEntriesタグのブロックの中で個々のブログ記事のIDを調べ、出力中のブログ記事のIDと異なるときだけ、その記事を出力するようにします。

ただ、出力中の記事が古くて、最新6件より前の記事であることもあります。
その場合、6件のブログ記事すべてで、「MTEntriesタグで出力する記事のIDが、出力中のブログ記事のIDと異なる」という条件に合ってしまうので、6件とも記事が出力されてしまい、最新5件の条件に合わなくなります。
そこで、「出力中のブログ記事のIDと異なる」という条件に加えて、「出力したブログ記事が5件未満」という条件も満たしたときだけ、その記事を出力するようにします。

具体的には、以下のようにテンプレートを組みます。

<$mt:EntryID setvar="entryid"$>
<$mt:SetVar name="count" value="0"$>
<mt:Entries lastn="6">
  <mt:If tag="EntryID" ne="$entryid">
    <mt:If name="count" lt="5">
      ブログ記事の情報を出力する部分
      <$mt:SetVar name="count" op="++"$>
    </mt:If>
  </mt:If>
</mt:Entries>

1行目のMTEntryIDタグで、現在出力中のブログ記事のIDを変数entryidに代入します。
2行目のMTSetVarタグでは、変数countに0を代入します。
この変数で、出力済みのブログ記事の件数を数えます。

3行目のMTEntriesタグで、最近の6件のブログ記事を読み込みます。
そして、4行目と5行目のMTIfタグで、個々の記事のIDが出力中の記事のID(変数entryid)と異なり、かつ出力済みの記事の件数(変数count)が5未満のときだけ、6行目によってその記事の情報が出力されます。
また、記事を出力したときには、7行目のMTSetVarタグで、出力済みの記事の件数(変数count)を1増やします。

3.記事のリストを出力したときだけその前後にHTML等を出力する

2.の手順で、最新5件のブログ記事のリストを出力することができます。
このブロックの前後にHTML等を入れれば、記事のリストをHTML等で囲むことができます。

しかし、状況によっては、記事のリストが出力されないこともあります。
その場合、前後のHTML等だけが出力されてしまうことになります。

そこで、記事のリストを直接に出力せずに、いったん変数に代入するようにします。
そして、MTEntriesタグのブロックの後で、変数countの値を判断して、値が0でない(=リストに1件以上記事があった)ときだけ、前後のHTML等と記事のリストを出力するようにします。

ここまでの話を元に、先ほどのテンプレートを書き換えると、以下のようになります。
MTEntriesタグの「setvar="related_entries"」のモディファイアで、記事のリストが変数related_entriesに代入されます。

<$mt:EntryID setvar="entryid"$>
<$mt:SetVar name="count" value="0"$>
<mt:Entries lastn="6" setvar="related_entries">
  <mt:If tag="EntryID" ne="$entryid">
    <mt:If name="count" lt="5">
      ブログ記事の情報を出力する部分
      <$mt:SetVar name="count" op="++"$>
    </mt:If>
  </mt:If>
</mt:Entries>
<mt:If name="count">
  リストの前に出力するHTML等
  <$mt:GetVar name="related_entries$>
  リストの後に出力するHTML等
</mt:If>

4.質問の例のテンプレート

ここまでの話から、質問の例についてテンプレートを作ると、以下のようになります。

<mt:If name="entry_archive">
  <$mt:EntryID setvar="entryid"$>
  <$mt:SetVar name="count" value="0"$>
  <mt:EntryIfTagged>
    <mt:SetVarBlock name="Sametags"><mt:EntryTags glue=' OR '><$mt:TagName$></mt:EntryTags></mt:SetVarBlock>
    <mt:Entries lastn="6" tags="$Sametags" setvar="related_entries">
      <mt:If tag="EntryID" ne="$entryid">
        <mt:If name="count" lt="5">
          <li><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></li>
          <$mt:SetVar name="count" op="++"$>
        </mt:If>
      </mt:If>
    </mt:Entries>
  <mt:Else>
    <$mt:EntryCategory setvar="Samecat"$>
    <mt:Entries lastn="6" category="$Samecat" setvar="related_entries">
      <mt:If tag="EntryID" ne="$entryid">
        <mt:If name="count" lt="5">
          <li><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></li>
          <$mt:SetVar name="count" op="++"$>
        </mt:If>
      </mt:If>
    </mt:Entries>
  </mt:EntryIfTagged>
  <mt:If name="count">
    <div class="widget-related-entries widget-archives widget">
      <h3 class="widget-header">関連記事</h3>
      <div class="widget-content">
        <ul>
          <$mt:GetVar name="related_entries"$>
        </ul>
      </div>
    </div>
  </mt:If>
</mt:If>

MTEntryIfTaggedタグとMTElseタグの間(5~13行目)は、出力中のブログ記事と同じタグの記事のリストを作る部分です。
5行目のMTSetVarBlockタグで、記事のタグを「OR」で連結し、変数Sametagsに代入します。
そして、5行目のMTEntriesタグで、tagモディファイアに変数Sametagsの値を指定し、同じタグを持つ記事を読み込みます。

MTElseタグとMTEntryIfTaggedタグの閉じタグの間(15~23行目)は、ブログ記事にタグがないときに、出力中のブログ記事と同じカテゴリに属する記事のリストを作る部分です。

そして、最後の部分(25行目以降)は、記事のリストを出力する部分です。
25行目のMTIfタグで、変数countの値が0でない(=リストに記事がある)ときだけ、リストとその前後のHTMLを出力します。

5.変数や条件判断は必須

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