mtde.info

Movable Type Developers Express

このカテゴリでは、Movable Type 4 でよく使用されるようになった「変数」についての解説を行っています。

『変数』カテゴリ内のエントリ一覧

変数とは

2008年1月29日 23:14 | Writer: apstar | 記事本文

変数とは、Wikipediaによると、以下のように定義されています。

数学、特に解析学において変数(へんすう、variable)とは、未知の、あるいは不定の数・対象を表す文字記号のことである。代数学の文脈では不定元(ふていげん、indeterminate)ともいう。また、記号論理学などでは(変数の表す対象が「数」に限らないという意味合いを込めて)変項(へんこう)ともいう。

変数とはの続きを読む

変数の初期化

2008年1月29日 23:57 | Writer: apstar | 記事本文

変数は、初期化することができます。変数の初期化とは、変数へ最初にセットしておきたい値を明示的に代入しておくこと(ゼロ("0")やヌルストリング("")の場合が多い)です。変数の初期化は必ずとも必須ではないですが、場合によっては初期化が必要なケースもあります。

変数の初期化の続きを読む

変数の代入

2008年1月30日 00:28 | Writer: apstar | 記事本文

変数へ値をセットすることを「代入」と呼びます。

Movable Typeでは、変数における厳格な型(文字列(=ことば)、数値(=値)、などetc)はないです。Aという変数へ"とうきょう"という言葉を代入すると、以後Aを参照すると"とうきょう"というデータを取得できます。Bという変数へ"500"という数値を代入すると、以後Bを参照すると"500"というデータを取得できます。

変数の代入を行うには、MTSetVarあるいはMTSetVarBlockテンプレートタグを用います。

変数の代入の続きを読む

変数の出力

2008年1月30日 00:38 | Writer: apstar | 記事本文

変数は、値を代入するだけでは意味がないです。変数へ格納された値を出力する処理を行わないと、(X)HTMLコード上には結果が出て来ないです。

変数から出力を行うには、MTGetVarテンプレートタグを用います。

変数の出力の続きを読む

変数の比較・処理分岐

2008年1月30日 20:17 | Writer: apstar | 記事本文

比較・処理分岐を行うテンプレートタグを用いると、変数自らの持つ値を、他の値と比較したうえでの処理分岐を行わせることが可能です。これはMovable Type 4にて変数を扱うにあたり、非常に重要です。

変数の比較・処理分岐を行うには、MTIf、MTElse、MTElseIf、MTUnlessテンプレートタグを用います。

変数の比較・処理分岐の続きを読む

変数の書き換え

2008年1月30日 20:37 | Writer: apstar | 記事本文

変数は、一度値を代入された後に、別の場所でもう一度別の値を代入すると、前の値は後から代入した値に書き換えられてしまいます。

変数の書き換えの続きを読む

ループ

2008年1月30日 20:58 | Writer: apstar | 記事本文

Movable Type 4.1からは、MTForあるいはMTLoopテンプレートタグで「ループ」と呼ばれる意図的な繰り返し処理が行えるようになりました。

MTForテンプレートタグの場合では、「始まりの数」と「終わりの数」を指定して、その範囲内で繰り返し処理を行わせます。

ループの続きを読む

配列

2008年1月30日 21:17 | Writer: apstar | 記事本文

配列とは、変数へ番号を与えたもので、Movable Typeでは

VarName[Index]

というような形で表します。VarNameが変数名、Indexが要素番号です。要素番号は通常0から連番で与えられます。

ループとあわせて使用すると非常に強力です。

配列の続きを読む

再構築するテンプレートを変数で制御する

2008年4月10日 23:59 | Writer: apstar | 記事本文

再構築するテンプレートを変数で制御する方法を説明します。

例えば、全てのテンプレートからインクルードされるサイドバーがあるとします。以下の非常に簡単なコードをサイドバーのモジュールに記述し、再構築します。

<MTCategoryLabel>

すると、以下のようなエラーが出ます。

テンプレート「メインページ」の再構築中にエラーが発生しました: テンプレートタグMTIncludeでエラーが発生しました: error in module サイドバー: テンプレートタグMTCategoryLabelでエラーが発生しました: 変数タグを不正なコンテキストで利用しようとしました。

テンプレートタグには、特定のテンプレートタグの内部や、特定の種類のアーカイブ内部でのみ使用可能なものがあります。この外側で使用した場合、メッセージにあるとおり「不正なコンテキスト」や「コンテキスト外」エラーが発生するのです。

ではどうやって回避するのか

先ほどの、再構築時にエラーとなったコードです。

<MTCategoryLabel>

このコードは、実は現在のカテゴリ位置を示す目的でサイドバーへ貼ろうとしていたものとします。

少し考えると、これには次のような矛盾があることに気がつかないでしょうか?

取得できるはずのないカテゴリラベルを取得しようとしている

メインインデックスページの再構築時には、MTCategoryLabelタグのみでのカテゴリのラベルは取得できません。MTCategoryLabelだけでは、カテゴリが特定できないためです。

同じ理由で、月別アーカイブやウェブページでもMTCategoryLabelタグのみでのカテゴリのラベルは取得できなさそうです。

実際は、MTCategoriesブロックタグで括ってあげると、全てのカテゴリラベルが取得できますが、今回は「トップページから特定のカテゴリのラベルを取得する」ことはしないとします。

そこで、このサイドバーの記述は、「カテゴリとエントリでのみ、有効にしたい」とします。そうすると、コードは以下のようになります。

<MTIf name="category_archive">
   <MTCategoryLabel>
</MTIf>
<MTIf name="entry_template">
   <MTCategoryLabel>
</MTIf>

このコードは、「カテゴリページあるいはエントリページでのみ、このコードを再構築する」という挙動を示します。

テンプレートの種類を識別するための予約変数および定義変数

再構築時に、「どのテンプレートでのみこのコードを適用する」といった制御には必須な、テンプレートの種類を識別するための 予約変数※1 および定義変数※2 を以下に記します。先ほどのサンプルコードは、これを利用しているわけです。

メインインデックスであるかどうか判断 ※2
MTIf name="main_index"
アーカイブインデックスであるかどうか判断 ※2
MTIf name="archive_index"
カテゴリ類全部であるかどうか判断 ※1
MTIf name="archive_listing"
カテゴリのみであるかどうか判断 ※1
MTIf name="category_archive"
エントリのみであるかどうか判断 ※1
MTIf name="entry_template"
ウェブページのみであるかどうか判断 ※1
MTIf name="page_template"
エントリおよびウェブページであるかどうか判断 ※1
feedback_template
日時用カテゴリのみであるかどうか判断 ※1
MTIf name="datebased_only_archive"
Auther用カテゴリのみであるかどうか判断 ※1
MTIf name="author_archive"
システムページであるかどうか判断 ※2
MTIf name="system_template"
検索ページであるかどうか判断 ※2
MTIf name="search_results_template"
コメントプレビューページであるかどうか判断 ※2
MTIf name="comment_preview_template"

※1 予約変数です。システム内部で予約されています。

※2 定義変数です。テンプレート先頭付近にMTSetVarで変数定義されています。

繰り返し処理における予約変数

2008年4月11日 00:02 | Writer: apstar | 記事本文

Movable Type では、ループ(繰り返し処理)において、以下のような予約変数を用いることができます。

__first__
ループ先頭の場合、実行されます。
__last__
ループ末尾の場合、実行されます。
__odd__
ループ奇数回目の場合、実行されます。
__even__
ループ偶数回目の場合、実行されます。
__index__
ループインデックスを、格納します。
__counter__
ループ回数を、格納します。

書き方は、MTForループで使用する場合は、以下を参考にしてください。

<MTFor var="x" from="1" to="10">

   <MTIf name="__first__">
      <p>先頭:<MTGetVar name="x"></p>
   </MTIf>

   <MTIf name="__last__">
      <p>末尾:<MTGetVar name="x"></p>
   </MTIf>

   <MTIf name="__odd__">
      <p>奇数:<MTGetVar name="x"></p>
   </MTIf>

   <MTIf name="__even__">
      <p>偶数:<MTGetVar name="x"></p>
   </MTIf>

   <MTIf name="__counter__">
      <p>カウンタ:<MTGetVar name="x"></p>
   </MTIf>

</MTFor>

MTForのほかに、MTLoop、MTEntries、MTCategoriesなどの、繰り返し処理を行えるブロックタグで使用することができます。また、そのループ中において条件分岐を行うMTIfでも使用することができます。

また、これらの予約変数は、既に代入(MTSetVar)されたものとして、通常の変数と同じように取り扱うことができます。以下のサンプルコードでは、MTGetvarテンプレートタグでループのインデックスを取得します。

<MTFor var="x" from="1" to="10">

   <MTGetVar name="__index__">

</MTFor>

この機能を用いたストライプ柄のエントリリストのサンプル

MTEntriesブロックタグを用いエントリリストを生成します。このとき、リストの背景色を、奇数回を白、偶数回を灰色とします。

CSS

.odd {
background:#ffffff;
}

.even {
background:#cccccc;
}

エントリリストのコード

<ul>
<MTEntries lastn="10">
<li class="<MTIf name="__odd__">odd<MTElse>even</MTIf>"><a href="<MTEntryPermaLink>"><MTEntryTitle></a></li>
</MTEntries>
</ul>

注意点

MTForで__index__、__odd__、__even__を用いる場合は、以下の点に注意してください。

MTにおける変数の有効範囲や、それに関わる問題点

2008年4月11日 00:04 | Writer: apstar | 記事本文

Movable Typeで使用される変数は、全てグローバル変数です。

本来、プログラムで変数を用いる場合には、有効範囲(スコープ)があります。どういうことかというと、有効範囲が広い変数は全ての範囲にて有効(グローバル)である、有効範囲が狭い変数は限られた範囲で使用後に破棄されてしまう(ローカル)、ということです。

変数が全てグローバルであるということは、どこかのモジュールで使用した変数を再利用する場合、初期化しておかないと既に値が入っていて変な挙動を示すことは十分に考えられます。

以下に一例を示します。

<p>変数初期化</p>
<MTSetVar name="hoge" value="1">
 
<p>1回目ループ</p>
<MTFor var="x" from="0" to="100">
   <MTSetVar name="hoge" op="++">
   <MTGetBar name="hoge"><br />
</MTFor>



...(なんかの処理)



<p>2回目ループ</p>
<MTFor var="x" from="0" to="100">
   <MTSetVar name="hoge" op="++">
   <MTGetBar name="hoge"><br />
</MTFor>

このコードには、ふたつのForループがあります。

最初のループでは、変数hogeを初期化し、ループ内で+1ずつ増やしていく処理(インクリメント)にて使用しています。

間に、「...(なんかの処理)」という処理を挟んでいるとしましょう。

2回目のループでは、変数hogeを初期化し忘れ、1回目と同じ結果を期待して、同じ処理を行っています。

このコードは、実行すると、2回目ループでのhoge変数の出力が102から開始されてしまいます。これは、hoge変数を初期化するのを怠ったためで、1回目のループ・インクリメント処理で使用したhoge変数に値が残ったままであるためです。

このひとつ目のループとふたつ目のループが、別モジュールに入っていたらとすると、意図しない不具合が発生して、しかも不具合の特定が難しくなってしまいます。

このコードを正しく動作させるためには、以下のように2回目のループの直前にhoge変数の初期化を行うコードを挿入すればOKです。

<p>変数初期化</p>
<MTSetVar name="hoge" value="1">
 
<p>1回目ループ</p>
<MTFor var="x" from="0" to="100">
   <MTSetVar name="hoge" op="++">
   <MTGetBar name="hoge"><br />
</MTFor>



...(なんかの処理)



<p>2回目ループ</p>
<MTSetVar name="hoge" value="1">
<MTFor var="x" from="0" to="100">
   <MTSetVar name="hoge" op="++">
   <MTGetBar name="hoge"><br />
</MTFor>

変数への適切な代入場所

2008年4月11日 00:07 | Writer: apstar | 記事本文

変数を使用するには、MTSetVarやMTSetVarBlockなどのテンプレートタグを用いて「変数への値の代入」を行います。

この代入をどこに記述するのかは、ケースバイケースです。

ケース1:テンプレート先頭付近

プログラムで変数を使用する場合は、一般的に「変数の宣言はコード先頭付近に置くほうが見通しが良い」とされます。Movable Typeにおいては、テンプレートの制御に使用する変数はこのケースに当てはまります。

以下はデフォルトテンプレートの、インデックステンプレート>メインページのテンプレートです。先頭行から5行が、テンプレート制御などに使用される変数の代入コードです。


<MTSetVar name="body_class" value="mt-main-index">
<MTSetVar name="main_template" value="1">
<MTSetVar name="main_index" value="1">
<MTSetVar name="sidebar" value="1">
<MTSetVarBlock name="title"><$MTBlogName encode_html="1"$></MTSetVarBlock>


<$MTInclude module="<__trans phrase="Header">"$>

<MTEntries>
    <$MTEntryTrackbackData$>
    <$MTInclude module="<__trans phrase="Entry Summary">"$>
</MTEntries>

<div class="content-nav">
    <a href="<$MTLink template="archive_index"$>"><__trans phrase="Archives"></a>
</div>

<$MTInclude module="<__trans phrase="Footer">"$>

ここで宣言している変数は(「わたし」というのはテンプレート自身)、

ということをインクルードされるモジュールへ知らせるような役目を持っています。

例えば、フッターモジュールで

<MTIf name="sidebar">
    <$MTInclude module="サイドバー"$>
</MTIf>

というコードがある場合、これはメインページには「わたしはsidebarに1をセットしています。」という記述があるので、メインページにはサイドバーがインクルードされるのです。もし、sidebar変数へ0が代入されていれば、サイドバーはインクルードされません。

このような記述は、デフォルトテンプレートでは以下の8つのテンプレートモジュールで行われています。「(1)(2)(3)テンプレートファイル」は、再構築されると一枚のXHTMLページになります。

(1)インデックステンプレート
  • main_index.mtml(メインページ)
  • archive_index.mtml(アーカイブインデックス)
(2)アーカイブテンプレート
  • entry.mtml(ブログ記事)
  • entry_listing.mtml(ブログ記事リスト)
  • page.mtml(ウェブページ)
(3)システムテンプレート
  • search_results.mtml(検索結果)
  • comment_response.mtml(コメント完了)
  • comment_preview.mtml(コメントプレビュー)

これらの変数は、インクルードするモジュール内で同じ変数名へ値をうっかり代入して上書きしないようにしましょう。

ケース2:使用直前

Movable Type 4.xのテンプレートでは細かいモジュール化が進んでおり、管理ページでの各モジュール間の移動に時間がかかります。変数を多用してカスタマイズを行っている場合、変数代入部分をいちいち一箇所へまとめたり、テンプレート先頭付近へまとめて記述すると、かえって効率が落ちる場合があります。

Movable Typeのテンプレート内で、変数を使用する場合のほぼ大多数を占めると思われるこのケースでは、使用直前に代入を行い、適切なコメントを記述しておくとわかりやすく、保守もやりやすいです。

例えば以下のコードでは、狙ったカテゴリのみを抽出してリスト化するコードですが、変数は使用直前に値の代入を行っています。

keyword変数はMTCategoriesブロックの外側で値を代入します。これは、ブロック内へ記述すると、カテゴリの個数回ループにてkeyword変数への無駄な代入が繰り返されるためです。

対してCurCat変数は、MTCategoriesブロックの内側で値を代入します。こうすると、MTCategoriesループでカテゴリ名が次々に切り替わり代入されます。

<MTSetVar name="keyword" value="カテゴリ1,カテゴリ3,カテゴリ5">
<ul>
<MTCategories>
   <MTSetVarBlock name="CurCat"><MTCategoryLabel></MTSetVarBlock>
   <MTIf name="keyword" like="$CurCat">
      <li><a href="<$MTCategoryArchiveLink$>"<MTIfNonEmpty tag="MTCategoryDescription"> title="<$MTCategoryDescription$>"</MTIfNonEmpty>><$MTCategoryLabel$> (<$MTCategoryCount$>)</a></li>
   </MTIf>
</MTCategories>
</ul>

上記コードに、MTIgnoreテンプレートタグでコメントを付与してみた例です。MTIgnoreテンプレートタグで括られた部分は、再構築時にはカットされますのでhtmlソースには出力されません。

なお、MTIgnoreでのコメント付与は必須ではありません。時間が経ったあとで、このコードを見て、何をやっているか解読する自信がない方は、つけておいたほうが良いかもしれません。

<MTIgnore> ***** 表示するカテゴリの一覧をカンマ区切りでkeyword変数へ代入 ***** </MTIgnore>
<MTSetVar name="keyword" value="カテゴリ1,カテゴリ3,カテゴリ5">
<ul>
<MTCategories>
   <MTIgnore> ***** CurCat変数=ループ中のカテゴリラベル ***** </MTIgnore>
   <MTSetVarBlock name="CurCat"><MTCategoryLabel></MTSetVarBlock>
   <MTIgnore> ***** keyword変数内にCurCat変数が含まれるかチェック ***** </MTIgnore>
   <MTIf name="keyword" like="$CurCat">
      <li><a href="<$MTCategoryArchiveLink$>"<MTIfNonEmpty tag="MTCategoryDescription"> title="<$MTCategoryDescription$>"</MTIfNonEmpty>><$MTCategoryLabel$> (<$MTCategoryCount$>)</a></li>
   </MTIf>
</MTCategories>
</ul>

便利なコメントアウトの仕方

2008年4月11日 00:08 | Writer: apstar | 記事本文

Movable Typeには、バージョン4以前からMTIgnoreというテンプレートタグがあります。このテンプレートタグを用いて、コメント行ももちろんですが、実験中のコードなどをコメント化することが可能です。

本家のドキュメントにも記述はありますが、あまり詳しく書いていませんのでここで説明します。

基本コードは以下のようになります。コメントアウトしたい部分をMTIgnoreタグで括ってあげるだけです。

<MTIgnore>
コメントアウトしたいコード
</MTIgnore>

コメント行として使う

コード中のコメント行として使用することができます。以下は、わかりづらいと思われる部分にコメント行を付加してみた例です。なお、このMTIgnoreテンプレートタグを用いて記述したコメント行は、再構築時にはカットされ、htmlソース中には出力されません。

<MTIgnore> ***** 表示するカテゴリの一覧をカンマ区切りでkeyword変数へ代入 ***** </MTIgnore>
<MTSetVar name="keyword" value="カテゴリ1,カテゴリ3,カテゴリ5">
<ul>
<MTCategories>
   <MTIgnore> ***** CurCat変数=ループ中のカテゴリラベル ***** </MTIgnore>
   <MTSetVarBlock name="CurCat"><MTCategoryLabel></MTSetVarBlock>
   <MTIgnore> ***** keyword変数内にCurCat変数が含まれるかチェック ***** </MTIgnore>
   <MTIf name="keyword" like="$CurCat">
      <li><a href="<$MTCategoryArchiveLink$>"<MTIfNonEmpty tag="MTCategoryDescription"> title="<$MTCategoryDescription$>"</MTIfNonEmpty>><$MTCategoryLabel$> (<$MTCategoryCount$>)</a></li>
   </MTIf>
</MTCategories>
</ul>

再利用したいかも、という箇所をとりあえず残しておく

2種類のコードを書いて、双方を比べる際などに使用すると、開発の効率は一気に上がります。

以下のコードは、このmtde.info開発中の際のスタイルシートのコードで、固定幅にするかリキッドレイアウトにするかを何度も切り替え、調整を行っていたときのものです。もしMTIgnoreテンプレートタグが無ければ、切り替えが面倒になりますので、初めからリキッド固定のみしかテストしなかったと思います。

コード中にもありますが、MTIgnoreテンプレートタグは多重の入れ子にすることも可能です。

<MTIgnore>定数セクション</MTIgnore>

<MTIgnore>色の設定</MTIgnore>
<MTSetVar name="COLOR_TEXT" value="#333333">                  <MTIgnore>Cテキスト色</MTIgnore>
<MTSetVar name="COLOR_TEXT_A" value="#104e8b">                <MTIgnore>Cリンクテキスト色</MTIgnore>
<MTSetVar name="COLOR_TEXT_A_HOVER" value="#ff7f00">          <MTIgnore>Cリンクテキストホバー色</MTIgnore>
<MTSetVar name="COLOR_TEXT_R" value="#ffffff">                <MTIgnore>RCテキスト色(リバース)</MTIgnore>
<MTSetVar name="COLOR_TEXT_A_R" value="#ffffff">              <MTIgnore>RCリンクテキスト色(リバース)</MTIgnore>
<MTSetVar name="COLOR_TEXT_A_HOVER_R" value="#ff7f00">        <MTIgnore>RCリンクテキストホバー色(リバース)</MTIgnore>

<MTIgnore>ヘッダとフッタ</MTIgnore>
<MTSetVar name="COLOR_BACKGROUND_HEADER" value="#ffffff">     <MTIgnore>Cバック色(ヘッダ)</MTIgnore>
<MTSetVar name="HEIGHT_HEADER" value="150px">                 <MTIgnore>H高さ(ヘッダ)</MTIgnore>
<MTSetVar name="COLOR_BACKGROUND_FOOTER" value="#333333">     <MTIgnore>Cバック色(フッタ)</MTIgnore>
<MTSetVar name="HEIGHT_FOOTER" value="32px">                  <MTIgnore>H高さ(フッタ)</MTIgnore>

<MTSetVar name="COLOR_BACKGROUND_GLOBALNAVI" value="#333333"> <MTIgnore>Cバックグラウンド色(グローバルナビゲーション)</MTIgnore>

<MTIgnore>
<MTIgnore>固定幅</MTIgnore>
<MTSetVar name="WIDTH_HEADER" value="100%">                   <MTIgnore>W幅(ヘッダ)</MTIgnore>
<MTSetVar name="WIDTH_BACKGROUND_GLOBALNAVI" value="100%">    <MTIgnore>W幅(グローバルナビ)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_TOTAL" value="1000px">          <MTIgnore>W幅(メイン総合)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_MAIN" value="575px">            <MTIgnore>W幅(メイン)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_MAIN2" value="770px">           <MTIgnore>W幅(メイン)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_SUB" value="195px">             <MTIgnore>W幅(サイドバー1)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_EXTRA" value="195px">           <MTIgnore>W幅(サイドバー2)</MTIgnore&gt;
<MTSetVar name="WIDTH_FOOTER" value="100%">                   <MTIgnore>W幅(フッタ)</MTIgnore>
</MTIgnore>

<MTIgnore>リキッド(96%で)</MTIgnore>
<MTSetVar name="WIDTH_HEADER" value="100%">                   <MTIgnore>W幅(ヘッダ)</MTIgnore>
<MTSetVar name="WIDTH_BACKGROUND_GLOBALNAVI" value="100%">    <MTIgnore>W幅(グローバルナビ)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_TOTAL" value="90%">             <MTIgnore>W幅(メイン総合)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_MAIN" value="52%">              <MTIgnore>W幅(メイン)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_MAIN2" value="74%">             <MTIgnore>W幅(メイン)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_SUB" value="22%">               <MTIgnore>W幅(サイドバー1)</MTIgnore>
<MTSetVar name="WIDTH_CONTENT_EXTRA" value="22%">             <MTIgnore>W幅(サイドバー2)</MTIgnore>
<MTSetVar name="WIDTH_FOOTER" value="100%">                   <MTIgnore>W幅(フッタ)</MTIgnore>

<MTSetVar name="POSITION_HEADMARGIN_LEFT" value="5%">         <MTIgnore>P位置(サイトタイトル)</MTIgnore>
<MTSetVar name="POSITION_HEADMARGIN_RIGHT" value="5%">        <MTIgnore>P位置(検索)</MTIgnore>
エントリ
タグ
はじめに
導入編
ローカル環境
変数
サンプル
その他
トラブル集
2008 mtde.info