コンテンツタイプとjsonとカンマの問題

top2019_0329.jpgMovableTypeのバージョンも7となり、コンテンツタイプなるモノが追加されました。
バージョンが7になってからMTに触れる機会がすくなった訳ですが、この度久々に扱い機会に恵まれました。
備忘録として残したいと思います。

■コンテンツタイプについて、実務的な参考ページです。
Movable Type 7 の機能 「コンテンツタイプ」でレシピサイトを作る

お題
今回のお題は。300店舗以上ある店舗情報の中から、ページにアクセスする度にランダムで5店舗を表示させたい。
店舗の登録はコンテンツタイプを使用。尚ページはスタティック(html)である。

ということで、ざっくりとやりたいことをまとめると

①コンテツタイプの内容をjson形式で出力したい。
②出力されたjsonを元にランダムで5店舗を表示。(ココはJSなので省きます)

表示させたい内容は店舗情報から「パーマリンク」「サムネイル画像」「店名」とします。
※サムイル画像は登録が無ければ「準備中」の画像を出力することを想定

準備したソースコードは以下となります。

[
<mt:Contents content_type="店舗情報一覧"><mt:For regex_replace="/^[\ \t\r\n]+/mg","">
  {
    "path":"<mt:ContentPermalink>",
    "thumbnails": "<mt:ContentField content_field="店舗のメイン画像"><$mt:AssetThumbnailURL height="285" square="1"$><mt:Else><mt:WebsiteURL>img/common/shop_thumbnail_noimg.jpg</mt:ContentField>",
    "shopname": "<mt:ContentField content_field="店名"><mt:ContentFieldValue></mt:ContentField>"
  }</mt:For><mt:unless __last__>,</mt:unless __last__></mt:Contents>
]

無事にjsonへ出力ができましたが、ここで問題が...
「準備中」の画像が掲載されている店舗が多すぎじゃね?と。

要望
300店舗に対して画像が登録されているのは50店舗弱。確かに「準備中」の店舗が多々表示されるのは頷けます。そこで、画像が登録されている店舗からランダムで表示できないかな?という要望が。

問題発生
修正の際にハマったのが「,」問題。
jsonはデータの最後にカンマがあると、エラーになってしまします。その問題を解決する方法としてMTunlessの登場となります!しかし、期待した動きにはならず頭を抱えます。

ちなみに考え方として、店舗全体からメイン画像の登録があるものを取得して、データの最後はカンマをつけない。という感じです。
MTContentField内で必要な情報が出力さているのでMTunlessが使えるものだと思い込んでいました。この思い込みが個人的な負のループのはじまりでしたw

※MTunlessを使用せず「,」を直接つければ表示されますが、最後のデータにもカンマがついてしまいます。

<mt:Contents content_type="店舗情報一覧">
<mt:ContentField content_field="店舗のメイン画像">
{・・・・}<mt:unless __last__>,</mt:unless __last__>
<mt:Else>
</mt:ContentField>
</mt:Contents>

修正バージョンは1店舗、1画像というルールでは有効な感じなりそうです。

<mt:Contents content_type="店舗情報一覧"><mt:For regex_replace="/^[\ \t\r\n]+/mg","">
  <mt:ContentField content_field="店舗のメイン画像">
  <mt:SetVarBlock name="shopimg" function="push" strip_linefeeds="1"><mt:ContentFieldValue></mt:SetVarBlock>
  </mt:ContentField>
</mt:For></mt:Contents>
[
<mt:Loop name="shopimg" regex_replace="/^[\ \t\r\n]+/mg","">
<mt:Var name="__value__">
{<mt:Contents content_type="店舗情報一覧" field:ID情報="$__value__">
    "contentsid":"<mt:ContentID>",
    "path":"<mt:ContentPermalink>",
    "thumbnails": "<mt:ContentField content_field="店舗のメイン画像"><$mt:AssetThumbnailURL height="285" square="1"$><mt:Else><mt:WebsiteURL>img/common/shop_thumbnail_noimg.jpg</mt:ContentField>",
    "shopname": "<mt:ContentField content_field="店名"><mt:ContentFieldValue></mt:ContentField>"
  </mt:Contents>}<mt:unless __last__>,</mt:unless __last__>
</mt:Loop>
]

想定した方法は、
①画像が登録さているフィールドの画像の値を取得する
②取得できた画像の値を配列へ
③配列をループさせる事で出力
④取得した画像の値をfield:でマッチングさせて店舗データを出力
⑤ループ処理に伴いMTunlessの動作を確認

最後に「,」が表示されてしまう問題が解決できました。

懸念点
例えばチェーン店や、大型商業施設など同じ画像を使いまわしていると一つの値で複数の店舗が取得されてしまい結果、jsonが壊れるカタチになります。
運用上のルールがネックになりますが、合致すれば御の字になりそうです。(ただまだまだ改善の余地はあります)

まとめ
・MTContentFiel内ではMTunlessが動作しないみたいなので、MTloopが動作するカタチに変更
・条件は取得する値がユニークであり、1つのコンテンツデータのみで使用されていること

MT7になってコンテンツタイプが扱えるに様になったのは大きいですね。
癖はありますが、コツが分かればそれなりに扱えます。
ただ、コンテンツタイプを横断したデータのやりとりはサーバへの負荷が大きいみたいで設計や仕様を考える上ではボトルネックになりそうだと思いました。