Movable Type の配列・ハッシュで誤解していたこと

これは Movable Type Advent Calendar 2014 の14日目の記事です。
今年も早いもので、あっという間に年末ですね。。。

さて、最近になって配列やハッシュを利用し、テンプレートタグだけで処理をする機会が増えました。

Movable Type 3 から使っているものの、今更ながらに気づいたことがいくつかありましたので、備忘録をかねて共有してみます。

そもそも、Movable Type の配列・ハッシュとは?

配列やハッシュの基本は公式リファレンスで解説されているので、そちらにお任せを w

配列、ハッシュ、<mt:loop>、<mt:for> | movabletype/Documentation Wiki:
https://github.com/movabletype/Documentation/wiki/Japanese-mtml-guide-3-3

variable タグを含むテンプレートタグ | テンプレートタグリファレンス:
http://app.movabletype.jp/mt/mt-search.cgi?IncludeBlogs=3&tag=variable&SearchSortBy=title&SearchResultDisplay=ascend

あわせて VarDump プラグインを利用すれば、変数の構造を簡単に確認できます。

alfasado/mt-plugin-var_dump:
https://github.com/alfasado/mt-plugin-var_dump

name / key / setvar モディファイアの値は日本語表記できる

公式リファレンスはもちろん、過去に目にした書籍やブログ記事などで変数名(ハッシュのキー)はいつも半角英数で記述されているため、てっきり「できないもの」と思い込んでましたが、日本語表記でも動くのですね。

ただし、下記コードのように「$変数名」の形で参照することはできません。

<mt:EntryTitle setvar="記事タイトル" />
<mt:Setvar name="タイトル" value="$記事タイトル" />
<mt:Var name="タイトル" /> <!-- 「$記事タイトル」と出力される -->

実際に利用することはないと思いますが、意外な発見でした。

MTLoop は入れ子にできる

これも単に試していなかっただけなのですが、下記のように入れ子になった MTLoop も普通に処理されるのですね。

<mt:Loop name="hashSample">
  __key__=<mt:Var name="__key__" /><br>
  <mt:Loop name="__value__" sort_by="key">
    __subKey__=<mt:Var name="__key__" />:__subValue__<mt:Var name="__value__" /><br>
  </mt:Loop>
</mt:Loop>

もしや?と思ってやってみたら、Movable Type 5.2.x でも大丈夫でした。

index / key モディファイアで悶々とする

インデックス番号を明示的に指定して配列を作ろうとしたとき、頭の中では下記と同じ出力結果になるだろうと考えていました。

<?php
  $hashSample = array(
     1 => 'hoge',
    10 => 'hoge10',
     5 => 'hoge5'
  );

  ksort($hashSample, SORT_NUMERIC);

  foreach ($hashSample as $key => $value) {
    echo $key . ':' . $value . '<br>' . PHP_EOL;
  }
?>

<!-- 出力結果 -->
1:hoge
5:hoge5
10:hoge10

ところが、MT タグで同じように値をセットしたところ、思いもよらない結果に。。。

<mt:SetVar name="hashSample" />
<mt:SetVar name="hashSample" index="1" value="hoge1" />
<mt:SetVar name="hashSample" index="10" value="hoge10" />
<mt:SetVar name="hashSample" index="5" value="hoge5" />

<mt:Loop name="hashSample">
  <mt:Var name="__counter__" op="--" />:<mt:Var name="__value__" /><br>
</mt:Loop>

<!-- 出力結果 -->
0:
1:hoge1
2:
3:
4:
5:hoge5
6:
7:
8:
9:
10:hoge10

無駄なループを避けるため、key モディファイアが無難かな?と思いきや。。。

<mt:SetVar name="hashSample" />
<mt:SetHashVar name="hashSample">
  <mt:SetVar name="1" value="hoge1" />
  <mt:SetVar name="10" value="hoge10" />
  <mt:SetVar name="5" value="hoge5" />
</mt:SetHashVar>

<mt:Loop name="hashSample" sort_by="key">
  <mt:Var name="__key__" />:<mt:Var name="__value__" /><br>
</mt:Loop>

<!-- 出力結果 -->
1:hoge
10:hoge10
5:hoge5

MTLoop のキーを基準とする並び替えでは numeric サブモディファイアが使えないということを覚えました。

sort_by モディファイア なしの MTLoop は、結果がランダムになる

以前、DataAPI のレスポンスを眺めていて不思議に感じたことでもあるのですが、sort_by モディファイアの指定がない MTLoop が実行されたとき、出力結果は(スタティックの場合)再構築するごとに変わってしまうのですね。

記事データなどの更新にあわせてであれば、内部的なルールがあるのだろう・・・と納得できるものの、個人的にモヤッとしました。

2次元ハッシュの値も、意外と簡単に変更できる?

2次元ハッシュの値は、一旦別の変数に入れたものに key モディファイア を指定すれば取得できます。

<!-- 間違った例 -->
<mt:Var name="hashSample{foo}" key="bar" />
<mt:Var name="hashSample{foo}{bar}" />

<!-- 正しい例 -->
<mt:Var name="hashSample" key="foo" setvar="hashSub" />
<mt:Var name="hashSub" key="bar" />

これと同じように、値を変更することもできるのですね。

<mt:Var name="hashSample" key="foo" setvar="hashSub" />
<mt:SetVar name="hashSub" key="bar" value="hoge" />

この後 MTLoop で出力すると値が上書きされていることを確認できるものの、前述の VarDump プラグインの出力結果では正しくセットされていたり・いなかったり・・・なので、素直にループ処理の中で更新した方がよいのかも?とは思いつつ。

最後に

今回は配列やハッシュについて気づいた点をまとめてみましたが、他にも過去に覚えたことを引きずっている可能性が否定できず、折りに触れ初心にかえって基本を見直すことは大事だな・・・と改めて感じました。

ということで。。。
先日発足した東北界隈を中心とする Movable Type ユーザーグループもよろしくお願いいたします w

MT東北(Facebook ページ):
https://www.facebook.com/mt.tohoku