カンマ区切りのカスタムフィールドの値で記事を並べ替える

MTQに「カスタムフィールドの値(複数)による並び替え」という質問がアップされていました。
この質問に答えます。

1.質問の内容

質問の内容は以下の通りです。

以下のような記事があるとします。
それぞれの記事のカスタムフィールドには、4桁の数値がカンマ区切りでいくつかずつ入力されています。

記事タイトルあるカスタムフィールドの値
記事Ahoge0907,2307,0322
記事Bfoo1255,0704
記事Ctest0505,0704
.........

この時に、カスタムフィールドの4桁の値を元に、記事を並べ替えて出力したいとのことです。
値の個数分だけ、同じ記事がリストに出現します。
例えば、上のような記事から、以下のような出力を得たいとのことです。

0322:タイトル:hoge
0505:タイトル:test
0704:タイトル:foo
0907:タイトル:hoge
1255:タイトル:foo
2307:タイトル:hoge

なお、元の記事を見ると、記事Bと記事Cに、4桁の値として「0704」が入力されています。
このように、複数の記事で同じ値が入力されているときには、上の出力結果からすると、最初に読み込んだ記事を出力する仕様のようです。

2.考え方

記事等のオブジェクトを、何らかの値で並べ替えて出力したいときには、ハッシュを使います。
ハッシュの個々の要素では、キーとして並べ替えに使う値を指定します。
そして、要素の値として、出力する内容を代入します。

今取り上げている例の場合、以下の手順でハッシュを作ります。

  • 1.記事を順に読み込みます。
  • 2.記事のカスタムフィールドの値を、カンマで分割して配列に代入します。
  • 3.配列の個々の要素を順に繰り返します。
  • 4.配列の個々の要素の値が4桁の数値になっていますので、それをハッシュのキーにします。
  • 5.ハッシュの値として、出力する内容(記事のタイトル等)を代入します。
    ただし、ハッシュに同じキーの要素がすでにあるときは、代入を行いません。
  • 6.ハッシュをキーで並べ替えて、値を順に出力します。

例に挙げた3つの記事の場合、1つ目の記事を読み込んだ時点では、ハッシュが以下のようになるようにします。

キー
0907「hoge」の記事のタイトル等
2307「hoge」の記事のタイトル等
0322「hoge」の記事のタイトル等

2つ目の記事を読み込んだ時点では、以下のようにその記事の情報をハッシュに追加します。

キー
0907「hoge」の記事のタイトル等
2307「hoge」の記事のタイトル等
0322「hoge」の記事のタイトル等
1255「foo」の記事のタイトル等
0704「foo」の記事のタイトル等

同様の手順で、3つ目の記事もハッシュに追加します。
ただし、キーが「0704」の要素はすでにありますので、それはハッシュに追加しません。
最終的なハッシュは、以下のようになります。

キー
0907「hoge」の記事のタイトル等
2307「hoge」の記事のタイトル等
0322「hoge」の記事のタイトル等
1255「foo」の記事のタイトル等
0704「foo」の記事のタイトル等
0505「test」の記事のタイトル等

そして、ハッシュをキーで並べ替えます。

キー
0322「hoge」の記事のタイトル等
0505「test」の記事のタイトル等
0704「foo」の記事のタイトル等
0907「hoge」の記事のタイトル等
1255「foo」の記事のタイトル等
2307「hoge」の記事のタイトル等

最後に、ハッシュの値を順に出力します。

3.テンプレートの例

ここまでの話に基づいてテンプレートを組むと、以下のようになります。
なお、2行目の「MTEntry○○○」は、カスタムフィールドの実際のテンプレートタグ名に置き換えます。
また、カスタムフィールドの値をカンマで分割して配列に代入する際に、小粋空間様で配布されているSplitプラグインを使っています。

<mt:Entries>
  <mt:Entry○○○ split="," setvar="keys">
  <mt:Loop name="keys">
    <mt:Unless name="entries" key="$__value__">
      <mt:SetVarBlock name="entries" key="$__value__">
        <$mt:GetVar name="__value__"$>:<a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a>
      </mt:SetVarBlock>
    </mt:Unless>
  </mt:Loop>
</mt:Entries>
<mt:Loop name="entries" sort_by="key">
  <mt:If name="__first__"><ul></mt:If>
    <li><$mt:GetVar name="__value__"$></li>
  <mt:If name="__last__"></ul></mt:If>
</mt:Loop>

テンプレートの内容は以下の通りです。

1/10行目

記事を読み込みます。

2行目

カスタムフィールドの値をコンマで区切り、「keys」という名前の配列変数に代入します。

3/9行目

配列の個々の要素(=4桁の数値)を順に取り出して繰り返します。

5~7行目

「entries」という名前のハッシュに、要素を追加します。
要素のキーとして、配列の個々の要素(__value__)を使います。
また、要素の値として、出力したいHTMLを代入します。

4/8行目

ハッシュentriesに、すでに同一のキーの要素があるときは、5~7行目を実行しない(=要素を追加しない)ようにします。

11~15行目

ハッシュentriesをキーで並べ替えて、個々の要素の値を順に出力します。