mtde.info

Movable Type Developers Express

このカテゴリでは、Movable Type 4 で変数を扱う場合に参考になりそうなTipsを紹介します。

『Tips系』カテゴリ内のエントリ一覧

インクリメントカウント

2008年2月 3日 10:15 | Writer: apstar | 記事本文

インクリメントを利用したカウントは、慣れると非常に便利な機能です。

たとえば、「一部のエントリが画像アイテムを持っている」という条件で、画像アイテムを持つエントリのみ抽出するのは、インクリメントカウントを用いると、簡単に実現できます。

コード例

<!-- 数をカウントする変数は必ず初期化する -->
<MTSetVar name="ImageCount" value="0">

<!-- 画像アイテムを持つエントリのみ抽出する -->
<MTEntries>
   <MTEntryAssets type="image">
      <MTSetVar name="ImageCount" op="++">
      <MTSetVarBlock name="EntryLink[$ImageCount]"><$MTEntryPermalink$></MTSetVarBlock>
      </MTIf>
   </MTEntryAssets>
</MTEntries>

<!-- 取得した配列データを出力 -->
<MTFor var="x" from="1" to="$ImageCount">
   <MTGetVar name="EntryLink[$x]">
</MTFor>

インクリメントを利用したカウントで気をつけたいのは、カウント用の変数は必ず初期化せねばいけない点です。これを怠ると、Movable Type 4.1で確かめたのですが、多くの場合正常に動作しません。

このサンプルの場合は、<MTEntryAssets type="image">ブロックタグでエントリ中の画像をループさせ、<MTSetVar name="ImageCount" op="++">の一行でインクリメントカウントを行っています。つまり画像を持たないエントリはここを通過せず、インクリメントカウントは行われません。

また、この書き方であると、ひとつのエントリに画像が2枚あると、配列に同じデータが2つ入ることとなります。

インクリメントカウントを行って生成したImageCount変数は、サンプルにもあるように、その後のMTForループのtoモデファイアにそのまま使用することができます。

変数同士の演算

2008年2月 3日 10:42 | Writer: apstar | 記事本文

変数同士の演算を行いたい機会は非常に多いです。

例えば、以下に準備されたvar1変数とvar2変数を掛け合わせ、Answerという変数へ演算結果を代入する場合はどうするか、解説します。

<MTSetVar name="var1" value="25">
<MTSetVar name="var2" value="331">

例1:MTSetVarBlockを用いる

MTSetVarBlockでAnswer変数を作成、その内側で、var1とvar2の演算を行います。直感的にはわかりやすいコード。

<MTSetVarBlock name="Answer"><MTGetVar name="var1" value="$var2" op="*"></MTSetVarBlock>

例2:MTGetVarにSetVarモデファイアを用いる

MTGetVarは、opモデファイアが付与されていると単に内部演算を行うのみで、値が出力されることはない事を利用します。かつ、ここにsetvarモデファイアで変数名を指定すると、その変数へ演算結果を代入できます。また、このコードはMTSetVarと書くと正常動作しません。

<MTGetVar name="var1" value="$var2" op="*" setvar="Answer">

配列を用いた演算

2008年2月 3日 11:02 | Writer: apstar | 記事本文

配列を用いた演算では、注意すべき点があります。

それは、配列変数を用いた演算では、配列変数はnameモデファイアにしか指定できないということです。

<MTSetVar name="var1" value="21">

<MTSetVar name="vars2[0]" value="78">
<MTSetVar name="vars2[1]" value="56">
<MTSetVar name="vars2[2]" value="65">
<MTSetVar name="vars2[3]" value="38">
<MTSetVar name="vars2[4]" value="71">

<MTSetVar name="Answer" value="0">
<MTFor var="x" from="0" to="4">
   <MTGetVar name="vars2[$x]" value="$var1" op="*" setvar="Answer">
   <MTGetVar name="var1">×<MTGetVar name="vars2[$x]">=<MTGetVar name="Answer"><br />
</MTFor>

このサンプルコードは、var1変数へ、vars[0]、vars[1]、vars[2]、vars[3]、vars[4]の配列変数の値を掛ける例です。サンプルコードでは、nameモデファイアへ配列のvarsを指定し、掛け合わせる値であるvalueモデファイアにvar1変数を指定しています。

上記コードで、もし、演算部分を<MTGetVar name="var1" value="$vars2[$x]" op="*" setvar="Answer">と書いてしまうと、うまくいかないです。新たに変数を宣言して、配列データを代入し、その変数をvalueモデファイアへ指定しても同様にうまくいかないです。

文字列の連結1

2008年2月 3日 11:39 | Writer: apstar | 記事本文

文字列を連結する場合には、MTSetVarテンプレートタグにてappendモデファイアを指定します。

下記の例では、変数var1の"12345"へ、変数var2の"67890"を、文字列として繋ぎ合わせています。結果、var1変数は"1234567890"と出力されます。

<MTSetVar name="var1" value="12345">
<MTSetVar name="var2" value="67890">
<MTSetVar name="var1" value="$var2" append="1">
2:<MTGetVar name="var1">

文字列の連結2

2008年2月 3日 11:52 | Writer: apstar | 記事本文

文字列を連結する場合には、MTSetVarBlockテンプレートタグとMTGetVarテンプレートタグをあわせてもよいです。

MTSetVarBlockにて出力結果を格納する変数名を定義し、そのブロック内部で繋ぎ合わせる文字列をMTGetVarで出力させます。

下記の例では、変数var1の"12345"へ、変数var2の"67890"を、文字列として繋ぎ合わせています。結果はMTSetVarBlockで定義したAnswer変数へ代入され、この結果は"1234567890"と出力されます。

<MTSetVar name="var1" value="12345">
<MTSetVar name="var2" value="67890">
<MTSetVarBlock name="Answer">
<MTGetVar name="var1"><MTGetVar name="var2">
</MTSetVarBlock>
<MTGetVar name="Answer">

また、この方法はループでも使用できます。下記の例では、MTForループ中で配列の値を次々とMTGetVarで出力させ、その出力結果を(MTForループ丸ごと括って)Answr変数と定義しています。結果、Answer変数には"あかさたな"という値が代入されます。

<MTSetVar name="vars[0]" value="あ">
<MTSetVar name="vars[1]" value="か">
<MTSetVar name="vars[2]" value="さ">
<MTSetVar name="vars[3]" value="た">
<MTSetVar name="vars[4]" value="な">

<MTSetVarBlock name="Answer">
<MTFor var="x" from="0" to="4">
<MTGetVar name="vars[$x]">
</MTFor>
</MTSetVarBlock>
<MTGetVar name="Answer">

数値のゼロ埋め

2008年2月 3日 12:05 | Writer: apstar | 記事本文

Movable Typeでは、カテゴリなどを並べ替える際にIDを利用すると、数値が文字列として評価されてしまい、並び順が意図したとおりにならないことが多々あります。

下記コードはカテゴリIDをキーに、カテゴリラベルをデータとしハッシュを生成、MTLoopで結果を並べるサンプルですが、MTLoopへsort_by="key"モデファイアを指定しても、カテゴリIDが1桁・2桁・3桁と混在すると、並び順が思うようにいかないです。これはMTLoopのsort_byモデファイアで並べ替えに用いられるキー(カテゴリID)が文字列で扱われているためです。

<MTCategories>
   <MTSetvarBlock name="keyvalue"><$MTCategoryID$></MTSetvarBlock>
   <MTSetvarBlock name="ShowCategory" key="$keyvalue"><$MTCategoryLabel$></MTSetvarBlock>
</MTCategories>

<MTLoop name="ShowCategory" sort_by="key">
   <p><$mt:getvar name="__key__"$> <$mt:getvar name="__value__"$></p>
</MTLoop>

1から20までのIDがある場合は、以下のように並びます。

これを改善するには、keyvalueキーへMTCategoryID取得・代入時にzero_pad="N"(Nは任意の桁数)としてゼロ埋め・桁あわせをするのが一番簡単です。こうすると、キーのIDが文字列評価されても正しく並べ替えされます。

<MTCategories>
   <MTSetvarBlock name="keyvalue"><$MTCategoryID zero_pad="4"$></MTSetvarBlock>
   <MTSetvarBlock name="ShowCategory" key="$keyvalue"><$MTCategoryLabel$></MTSetvarBlock>
</MTCategories>

<MTLoop name="ShowCategory" sort_by="key">
   <p><$mt:getvar name="__key__"$> <$mt:getvar name="__value__"$></p>
</MTLoop>

1から20までのIDがある場合は、以下のように並びます。

四捨五入

2008年2月 3日 12:19 | Writer: apstar | 記事本文

Movable Typeで数値の四捨五入を行う場合はJavaScriptを併用する方法があります。

<p>四捨五入</p>
<MTSetVarBlock name="RoundValue">
<SCRIPT language="JavaScript">
<!--
document.write(Math.round(4.321));
//-->
</SCRIPT>
</MTSetVarBlock>
<MTGetVar name="RoundValue">

このサンプルでは4.321を四捨五入し、結果は 4 と出力されます。

切り捨て

2008年2月 3日 12:50 | Writer: apstar | 記事本文

Movable Typeで数値の切り捨てを行う場合はJavaScriptを併用する方法があります。

<p>切り捨て</p>
<MTSetVarBlock name="FloorValue">
<SCRIPT language="JavaScript">
<!--
document.write(Math.floor(4.321));
//-->
</SCRIPT>
</MTSetVarBlock>
<MTGetVar name="FloorValue">

このサンプルでは4.321を切り捨てし、結果は 4 と出力されます。

切り上げ

2008年2月 3日 12:57 | Writer: apstar | 記事本文

Movable Typeで数値の切り上げを行う場合はJavaScriptを併用する方法があります。

<p>切り上げ</p>
<MTSetVarBlock name="CeilValue">
<SCRIPT language="JavaScript">
<!--
document.write(Math.ceil(4.321));
//-->
</SCRIPT>
</MTSetVarBlock>
<MTGetVar name="CeilValue">

このサンプルでは4.321を切り上げし、結果は 5 と出力されます。

乱数

2008年2月 3日 12:59 | Writer: apstar | 記事本文

Movable Typeで乱数を得たい場合はJavaScriptを併用する方法があります。

<p>乱数</p>
<MTSetVarBlock name="RndValue">
<SCRIPT language="JavaScript">
<!--
document.write(Math.floor(Math.random() * 10));
//-->
</SCRIPT>
</MTSetVarBlock>
<MTGetVar name="RndValue">

このサンプルでは、ページがリロードされるたびに0から9までの乱数が表示されます。

べき乗

2008年2月 3日 13:03 | Writer: apstar | 記事本文

Movable Typeで数値のべき乗を行う場合はJavaScriptを併用する方法があります。

<p>べき乗</p>
<MTSetVarBlock name="PowValue">
<SCRIPT language="JavaScript">
<!--
document.write(Math.pow(10,3));
//-->
</SCRIPT>
</MTSetVarBlock>
<MTGetVar name="PowValue">

このサンプルでは10を3乗し、結果は 1000 と出力されます。

平方根

2008年2月 3日 13:04 | Writer: apstar | 記事本文

Movable Typeで数値の平方根を求める場合はJavaScriptを併用する方法があります。

<p>平方根</p>
<MTSetVarBlock name="SqrtValue">
<SCRIPT language="JavaScript">
<!--
document.write(Math.sqrt(10000));
//-->
</SCRIPT>
</MTSetVarBlock>
<MTGetVar name="SqrtValue">

このサンプルでは10000の平方根を求め、結果は 100 と出力されます。

MTSetVarTemplateを用いた演算パッキングの例

2008年4月26日 09:50 | Writer: apstar | 記事本文

MTSetVarTemplateテンプレートタグの特性を用いた、演算機能パッキングの例を紹介します。

MTSetVarBlockとMTSetVarTemplateの機能の相違点は次のようになります。

MTSetVarBlock
再構築時には必ず実行される。
MTSetVarTemplate
再構築時に、MTSetVarTemplateで定義された変数が参照されたときのみ実行される。

例1:普通に演算コードを書いてみる

以下の例では、tmpVal1とtmpVal2の値を足し合わせ、結果を2で割り、整数丸めを行っています。演算結果がマイナスになった場合は、演算結果を0で置き換えます。

なお、tmpVal1とtmpVal2の値は、3セット準備されています。

※このような演算は、CSSで定義された、とあるブロック内に配置する画像のpaddingを、変数を用いて自動演算させたい場合に考えられます。

<MTSetVar name="tmpVal1" value="50">
<MTSetVar name="tmpVal2" value="33">
<MTSetVar name="tmpVal1" op="-" value="$tmpVal2">
<MTSetVar name="tmp" value="$tmpVal1">
<MTSetVar name="tmp" op="/" value="2">
<MTIf name="tmp" lt="0">
   <MTSetVar name="tmp" value="0">
</MTIf>
<p>1個目の計算値:<MTGetVar name="tmp" sprintf="%d"></p>

<MTSetVar name="tmpVal1" value="200">
<MTSetVar name="tmpVal2" value="100">
<MTSetVar name="tmpVal1" op="-" value="$tmpVal2">
<MTSetVar name="tmp" value="$tmpVal1">
<MTSetVar name="tmp" op="/" value="2">
<MTIf name="tmp" lt="0">
   <MTSetVar name="tmp" value="0">
</MTIf>
<p>2個目の計算値:<MTGetVar name="tmp" sprintf="%d"></p>

<MTSetVar name="tmpVal1" value="70">
<MTSetVar name="tmpVal2" value="200">
<MTSetVar name="tmpVal1" op="-" value="$tmpVal2">
<MTSetVar name="tmp" value="$tmpVal1">
<MTSetVar name="tmp" op="/" value="2">
<MTIf name="tmp" lt="0">
   <MTSetVar name="tmp" value="0">
</MTIf>
<p>3個目の計算値:<MTGetVar name="tmp" sprintf="%d"></p>

Movable Type 4以降で準備された変数演算は、便利ではあるものの、このような簡単な演算にも多数行に渡る「同じような」コードを書かねばならず、コードを書く効率が悪いですし、ソースの見通しが悪いです。

例2:MTSetvarTemplateで書き換えてみる

例1のコードをMTSetVarTemplateテンプレートタグで同等に書き換えた例が以下コードです。

<MTSetVarTemplate name="getpad">
<MTSetVar name="tmpVal1" op="-" value="$tmpVal2">
<MTSetVar name="tmp" value="$tmpVal1">
<MTSetVar name="tmp" op="/" value="2">
<MTIf name="tmp" ge="0">
   <MTGetVar name="tmp" sprintf="%d">
<MTElse>
   <MTSetVar name="tmp" value="0">
   <MTGetVar name="tmp" sprintf="%d">
</MTIf>
</MTSetVarTemplate>

...(中略)...

<MTSetVar name="tmpVal1" value="50">
<MTSetVar name="tmpVal2" value="33">
<p>1個目の計算値:<MTGetVar name="getpad"></p>

<MTSetVar name="tmpVal1" value="200">
<MTSetVar name="tmpVal2" value="100">
<p>2個目の計算値:<MTGetVar name="getpad"></p>

<MTSetVar name="tmpVal1" value="70">
<MTSetVar name="tmpVal2" value="200">
<p>3個目の計算値:<MTGetVar name="getpad"></p>

MTSetVarTemplateタグで囲まれた部分が、変数演算機能をパッキングした部分で、計算のたびに同じコードが使用されます。

「...(中略)...」より下の部分で、演算機能を利用するときのコードを書きます(が、ここには演算コードはひとつも書きません)。tmpVal1変数とtmpVal2へ値を代入し、<MTGetVar name="getpad">と書いてgetpad変数を参照すると、MTSetVarTemplateで括られた(これには変数名nameにgetpadが指定されている)部分が実行されるわけです。

MTSetVarTemplateで定義されたgetpad変数が一度も参照されなかった場合は、MTSetVarTemplateで括られたコード群は一度も実行されませんし、100回参照されれば100回実行されます。演算機会が多ければ多いほどその真価を発揮します。

この演算の頻度が非常に多い場合は、このMTSetvarTemplateの部分は個別にモジュール化し、テンプレート先頭付近でそのモジュールをインクルードさせると更にすっきりします。

Movable Typeでは変数はグローバル変数(どこからでも参照できる)で扱われます。他のモジュールから参照することができます。同時に、意図しない変数の書き換えを行ってしまわないように注意が必要です。

エントリ
タグ
はじめに
導入編
ローカル環境
変数
サンプル
その他
トラブル集
2008 mtde.info