各カテゴリの最新1件のエントリーを新しい順に並べるカスタマイズ

昨日、mixi の Movable Type のコミュニティで、以下のような質問があって、「あーこれならハッシュを使ってできるんじゃない?」と思ってテンプレートを考えていました。

  • 各カテゴリの最新エントリーを1つずつ表示
  • カテゴリは、エントリーの新しい順に自動で並び替え
  • 最新3件のカテゴリのみを表示(MTCategories lastn="3"的なイメージ)

で、今朝 mixi に投稿しようと思ったら、The blog of H.Fujimotoさんがハッシュを使ったやり方で答えだしていたので、僕はこっちでエントリーしておきます。

完成したソース

<mt:TopLevelCategories>
    <mt:Entries lastn="1">
    <mt:EntryDate format="%Y%m%d" setvar="entry_date" />
    <mt:SetVarBlock name="entry_list" key="$entry_date"><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$> (<$mt:CategoryLabel$>)</a></mt:SetVarBlock>
    </mt:Entries>
<mt:SubCatsRecurse />
</mt:TopLevelCategories>

<mt:SetVarBlock name="entry_lists"><mt:Loop name="entry_list" sort_by="key reverse">__<mt:GetVar name="__counter__" />__<li><mt:GetVar name="__value__" /></li></mt:Loop></mt:SetVarBlock>

<dt>各カテゴリの最新1件を新しいものから3つ表示</dt>
<dd>
  <ul>
    <mt:GetVar name="entry_lists" regex_replace="/__4__.*/","" regex_replace="/__[0-9]__/g","" />
  </ul>
</dd>

解説

テンプレートの考え方

まず、考え方の流れは次のとおりです。

  1. カテゴリを全部リストアップしながら、そのカテゴリの最新のブログ記事を1件出力する。この段階では、ブログ記事はカテゴリ名の順で並ぶ。
  2. リストアップされた記事を、投稿された順に並び替える。
  3. 最新3件を残して4件目以降はカットする。

ハッシュ変数 entry_list の作成

テンプレートの上段で、ハッシュ変数 entry_list を作成します。

<mt:TopLevelCategories>
  <mt:Entries lastn="1">
  <mt:EntryDate format="%Y%m%d" setvar="entry_date" />
  <mt:SetVarBlock name="entry_list" key="$entry_date"><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$> (<$mt:CategoryLabel$>)</a></mt:SetVarBlock>
  </mt:Entries>
<mt:SubCatsRecurse />
</mt:TopLevelCategories>

MTTopLevelCategories タグで、常にトップレベルカテゴリからカテゴリをリストアップします。

カテゴリをリストアップしながら、そのカテゴリ中の最新1件のブログ記事を取得し、20090118 のような形式の投稿日をキーとして、ハッシュ変数 entry_list に格納していきます。

ハッシュ変数 entry_list を投稿日が新しい順に並び替え

この時点でハッシュ変数 entry_list に格納されているブログ記事は、カテゴリ名順に並んでいます。これをキー(投稿日)を基準に並び替えて取得し、今度は配列変数 entry_lists に格納します。

このとき、次の段階で件数を絞り込むために、各項目の頭に「 __1__ 」のような番号を振っておきます。

最新3件を残して4件目以降はカット

この時点で、ブログ記事は各カテゴリの最新1件が、投稿日が新しい順に並びました。あとは、今回は最新3件だけ欲しいので、4件め以降はカットします。

ここではアナログ的に、regex_replace モディファイアを使います。MTFor タグを使うことも考えましたが、再構築時の負担が増える気がしたので、そちらの方法は考えるのをやめました。

<dt>各カテゴリの最新1件を新しいものから3つ表示</dt>
<dd>
  <ul>
    <mt:GetVar name="entry_lists" regex_replace="/__4__.*/","" regex_replace="/__[0-9]__/g","" />
  </ul>
</dd>

正規表現で、4件目以降、すなわち「 __4__ 」以降をすべてカットします。その後、「 __1__ 」という形式の連番をすべてカットします。

これで、最新3件のみが残ります。もし、最新5件のみ残すように変更したい場合は、ソース中の「 __4__ 」の部分を「 __6__ 」とすればOKです。

以上です。多分、The blog of H.Fujimotoさんの方は、もっとスマートな解決策を出してくれるんだと思います。

【2009-01-19 追記】

やはりカテゴリを記事が投稿された順に表示する(その2) - The blog of H.Fujimotoの方がスマートでした。僕も勉強になりました。

トラックバック

The trackback URL is "".

コメント

mixiで質問させていただいたモノです。
親切に教えてくださって本当にありがとうございました!
ハッシュの使い方がぜんぜん分からなかったのですが、
やっと意味が(なんとなく)わかりました。
MTってちゃんと極めればいろんなことができるんですね。

「カテゴリーの同カテゴリー内における最新エントリー順」を調べていて、辿り着きました。
MT2.6のころからこの形ができないものかと思ってはいましたが、ただ、けっこう高度な使い方ですよね。

こちらのページのものは正規表現まででてきますし、The blog of H.Fujimotoさんの方は変数の使い方が手慣れた人でないとなかなか見出せない方法です。ハッシュ自体プログラム的な考え方を理解していないと中々実際のコードで入れ込んでいくのは難しい面があり、さらに変数云々ですと、なかなかちゃんと理解するには厄介です。。
なんだか愚痴みたいになってますが、もっと容易くできないものでしょうか。
カテゴリーを担うタグが内包するエントリーの最新順でソートできればいいだけなのに。。。といつも思います。

ありがとうございます。
こちらの右にありますカテゴリーですと、

# Webデザイン (5)
エントリータイトル 【XHTML+CSS】
エントリータイトル 【JavaScript】
エントリータイトル 【jQuery】

# Movable Type (32)
エントリータイトル 【テンプレート】
エントリータイトル 【プラグイン】



という感じでして、肝心の挙動ですが、

・メインカテゴリー(WebデザインやMovable Type)自体の並び順も中身のエントリーにの最新のものに合わせて変動する
・中身のエントリー表示も最新順に並べる(最大3件程度表示)

という感じです。

例にあげてしまい恐縮なのですが、以下のサイト様ですと、
http://webbibo.com/
の「スタイルシートテクニック」という見出し以下の表示に近く、「フォント・リンク」や「イメージ・背景」といったカテゴリー部分が内部のエントリーに合わせて最新順に並んでほしいんです。
ちなみにここのサイトはそうなりませんが、今の状態で希望の表示になるとすれば、「イメージ・背景」のくくりが一番上になっていてほしいんです。

拙い説明ですみません。

>縛りはないんですよね?
です。

「カテゴリーを最新順に」って、アリガチな見た目だと思うので、以降のバージョンでタグとモディファイアを駆使して何とかできる程度になることを期待しています。

お付き合いありがとうございました。
為になる記事がたくさんあるので、今後も参考にさせてもらいます。

例にあげて頂いた「webbibo」の管理人です。為になる記事がたくさんありますね。CSSプロパティの記述順序はかなり参考になりました。これからも読ませていただくので、どうぞよろしくお願いします。

tinybeans様 はじめまして。たきぼんと申します。
会社の業務で、MTを使用したサイトを運営しているものです。

ネットで調べていてこちらの記事にたどり着きました。
私が管理している、会社のサイト(全体がMTでできています)
の中で、ちょうどこちらの記事の様な処理が必要となりましたので参考にさせていただきました。

http://www.satsumahome.com/

このたびこちらのサイトの
「さつまホームの現場からお届けする施工日記」
の部分に使わせていただき、目標としていた、「各カテゴリの
最新記事を1件ずつ表示する」を実現できました。解説も、初心者の私なりに読ませていただき、大変ためになりました。ありがとうございます。

ただ、最新3件の絞込みと、entry_listsの値のリプレイス(11番目以降の記事)がうまく処理できなくなってしまいました。

tinybeans様のスクリプトをそのまま貼った場合は正しく処理してくれましたので、私が変更させていただいた部分に何か問題があるのだと思います。
主な違いは、<MTEntries>の代わりに<MTEntriesHaveImages>という、プラグインに依存するタグを使用していることと、TABLEタグなどを使っていて、ループの中身が大きくなってしまっていることでしょうか。

こちらがテンプレートの該当部分になります。原因についてお気づきのことがございましたら、どうかアドバイスを賜りますようお願い申し上げます。

********************************************

<MTMultiBlog blog_ids="2">
<mt:TopLevelCategories>
<MTEntriesHaveImages lastn="1" limit_per_entry="1">
<mt:EntryDate format="%Y%m%d" setvar="entry_date" />
<mt:SetVarBlock name="entry_list" key="$entry_date">

<table>
<tr>
<td rowspan="2">
<MTEntryImages>
<a href="<MTEntryImageEntry><$MTEntryPermalink$></MTEntryImageEntry>"><img src="<$MTEntryImageSrc$>" width="<$MTEntryImageWidth cell_size="80,80"$>" height="<$MTEntryImageHeight cell_size="80,80"$>" alt="<$MTEntryImageAlt$>" /></a>
</MTEntryImages>
</td>
<td>
<h3 style="font-size: 12px;">
<a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a>
 <MTEntryCategories>
<a href="<$MTCategoryArchiveLink$>">[<$MTCategoryLabel cutfirstchar="3"$>]</a>
</MTEntryCategories>
 [<$MTEntryDate format="%y年%m月%d日"$>]</h3>
</td>
</tr>
<td>
<p style="font-size: 11px; margin-top: 0px; margin-bottom: 5px;">
<$MTEntryBody words="90"$>…</p>
</td>
</tr>
</table>

</mt:SetVarBlock>
</MTEntriesHaveImages>
<mt:SubCatsRecurse />
</mt:TopLevelCategories>

<mt:SetVarBlock name="entry_lists">
<mt:Loop name="entry_list" sort_by="key reverse">__<mt:GetVar name="__counter__" />__
<li><mt:GetVar name="__value__" /></li>
</mt:Loop>
</mt:SetVarBlock>

<dd>
<ul>
<mt:GetVar name="entry_lists" regex_replace="/__4__.*/","" regex_replace="/__[0-9]__/g","" />
</ul>
</dd>
</MTMultiBlog>

tinybeans様

先ほどご質問させていただきました、たきぼんです。

「entry_listsの値のリプレイス」(「__1__」などをカット)につきましては、<mt:SetVarBlock>~</mt:SetVarBlock>間の改行コードが悪さをしている事に気づきましたので、改行を全て取り払い、うまくいきました。

けれど件数の絞込みは、やはりうまくできませんでした。現在は公開する記事の方を調整して9~10件に抑えました。(正規表現が初心者でよくわからないのですが、このままではカテゴリーが10以上あったら対応できないと思いました)
希望としましては、カテゴリー数はこの状態で一覧表示の方だけ3件~5件に絞りたいと考えております。どうかよろしくご教示お願い申し上げます。

tinybeans様

たきぼんです。たびたび失礼します。

>けれど件数の絞込みは、やはりうまくできませんでした。
申し訳ありません。こちらの件も、改行コードが残っていたためとわかりました。
いろいろとお騒がせして、結局tinybeans様のスクリプト通りで解決できてしまった次第です。掲示板を汚してしまい申し訳なく思います。よろしければ削除して下さっても構いません。

ともあれ、tinybeans様のおかげで目的を達することができましたことに感謝いたします。

コメントする