画像のカスタムフィールドに値があるブログ記事だけを出力する

先ほど、MTQを見ていたところ、以下のような質問が上がっていました。

ブログ記事に写真のカスタムフィールドを作り、写真が選択されているエントリーの一覧を作成できないものかと考えているのですがどう記述したらうまくフィルタできるでしょうか?

質問された方は、MTEntriesタグの「field:○○○」のモディファイアでどうにかしようとしていました。
しかし、残念ながらその方法ではうまくいきません。
そこで、この質問に答えてみます。

1.少なくとも1つ以上のブログ記事でカスタムフィールドに画像がある場合

少なくとも1つ以上のブログ記事で、カスタムフィールドに画像がある場合は、比較的簡単です。
<mt:カスタムフィールドのタグ名Asset>タグのブロックは、画像があるカスタムフィールドの時しか処理されませんので、その性質を利用します。

例えば、画像のカスタムフィールドのタグ名を「MTEntryPhoto」にしているとします。
この場合、そのカスタムフィールドに画像がある記事をul/li要素でリストアップするなら、以下のようにすると良いです。

<ul>
<mt:Entries>
  <mt:EntryPhotoAsset>
    <li>
      <a href="<mt:EntryPermalink>"><img src="<mt:AssetURL>" width="160" class="asset-img-thumb" alt="<mt:EntryTitle>" /></a>
      <a href="<mt:EntryPermalink>"><mt:EntryTitle></a>
    </li>
  </mt:EntryPhotoAsset>
</mt:Entries>
</ul>

2.どのブログ記事のカスタムフィールドにも画像がないことがある場合

一方、どのブログ記事のカスタムフィールドにも画像がない場合、1.の方法だと空のul要素が出力されるという問題があります。
この問題は、繰り返しを2回行えば、何とか解決できます。

1回目の繰り返しで、画像があるブログ記事を抜き出し、出力したい内容を配列に保存します。
そして、2回目の繰り返しで、1回目の配列から要素を順に取り出し、出力していきます。
実際にテンプレートを組むと、以下のようになります。

<mt:Entries>
  <mt:EntryPhotoAsset>
    <mt:SetVarBlock name="push(photos)">
      <li>
        <a href="<mt:EntryPermalink>"><img src="<mt:AssetURL>" width="160" class="asset-img-thumb" alt="<mt:EntryTitle>" /></a>
        <a href="<mt:EntryPermalink>"><mt:EntryTitle></a>
      </li>
    </mt:SetVarBlock>
  </mt:EntryPhotoAsset>
</mt:Entries>

<mt:Loop name="photos">
<mt:If name="__first__"><ul></mt:If>
<$mt:GetVar name="__value__"$>
<mt:If name="__last__"></ul></mt:If>
</mt:Loop>

前半の処理では、カスタムフィールドに画像があった時だけ、その情報をマークアップして、「photos」という配列に格納していきます。
そして、後半の処理で、配列photosから要素を1つずつ順に取り出して出力します。

全てのブログ記事でカスタムフィールドに画像がない場合、前半の繰り返しを行っても、配列photosは空のままです。
そのため、後半のMTLoopタグの部分では何も出力されず、空のul要素は出力されません。

3.パフォーマンスは良くない

ここまでであげた方法では、ブログ記事をいったん全部読み込んでから、カスタムフィールドに画像がある記事を抜き出すという方法を取っています。
そのため、ブログ記事の数が多くなると、それに比例してパフォーマンスが落ちるという弱点があります。
この点には注意が必要です。