1/122
テンプレートタグのまとめ
2/122
プロフィール
3/122
テンプレートタグの基礎
4/122
テンプレートタグとは
•MTのテンプレートなどに記述するタグ(MTML)
•主にMTに保存したデータを出力
•HTML などのマークアップ言語に似たフォーマット
•「ファンクションタグ」と「ブロックタグ」の2種類
•モディファイアも...
5/122
テンプレートタグを使った簡単なサンプル1
ブログ名をindex.htmlに出力
インデックステンプレート
First Weblog
ブログ全般設定画面
再構築 index.html
<$mt:BlogName$>
6/122
テンプレートタグを使った簡単なサンプル2
投稿記事のタイトル・本文を
index.htmlに出力
インデックステンプレート
ブログ記事投稿画面
テスト1
テスト1です。
テスト2
テスト2です。
index.html再構築
<mt:...
7/122
管理画面とテンプレートタグの対応1
記事投稿画面
<$mt:EntryTitle$>
<$mt:EntryBody$>
<mt:EntryTags>
<$mt:EntryExcerpt$>
<$mt:EntryDate$>
<$mt...
8/122
管理画面とテンプレートタグの対応2
記事一覧画面
<mt:Entries>
9/122
フォーマット
10/122
共通的なフォーマット
<mt:XXXXX>
•ブラケット"<"と">"で括る
•"mt:"という接頭辞をつける
<mtXXXXX>
<MT:XXXXX>
<MtXXXXX>
上記でもOK
11/122
ファンクションタグ
12/122
ファンクションタグとは
•データの属性(ブログID、記事タイトルなど)を出力
•ブロックタグの中に記述しないと動作しないものがある
(そうでないものも多数)
→詳しくは「コンテキスト」の章で
13/122
ファンクションタグのフォーマット
<$mt:EntryTitle$>
<$mt:XXXXX$>
基本的に名称の前半がオブジェクト、後半が属性
タグの先頭と末尾に$をつける(なしでもOK)
14/122
ファンクションタグのオブジェクト(抜粋)
<$mt:Entryxxxx$>
<$mt:Pagexxxx$>
<$mt:Categoryxxxx$>
<$mt:Assetxxxx$>
<$mt:Commentxxxx$
>
<$mt...
15/122
ファンクションタグの属性(抜粋)
<$mt:xxxxName$>
<$mt:xxxxLabel$>
<$mt:xxxxTitle$>
<$mt:xxxxURL$>
<$mt:xxxxCount$>
<$mt:xxxxID$>
<$...
16/122
ブロックタグ
17/122
ブロックタグのフォーマット
<mt:XXXX>
:
</mt:XXXX>
•開始タグと終了タグを書く
•HTMLと同様、終了タグは"/"をつける
•ブロックに挟まれた部分を処理する
開始タグ
終了タグ
ブロック
18/122
ブロックタグの種類
<mt:Entries>
:
</mt:Entries>
主に「繰り返し」「関連オブジェクト」「条件判定」の3種類
<mt:EntryAssets>
:
</mt:EntryAssets>
繰り返し 関連オブジ...
19/122
ブロックタグ(繰り返し)
<mt:Entries>
:
</mt:Entries>
ブログ記事の繰り返し
<mt:Assets>
:
</mt:Assets>
アイテムの繰り返し
<mt:Blogs>
:
</mt:Blogs>
...
20/122
ブロックタグに書ける主なオブジェクト
ユーザー
トラックバック
フォルダ
タグ
アイテム
ウェブページ
ブログ記事
Websitesウェブサイト
ブロックタグオブジェクト
カテゴリ
ブログ
Authors
Pings
Folder...
21/122
ブロックタグ(関連オブジェクト)
<mt:EntryAssets>
:
</mt:EntryAssets>
ブログ記事のアイテムの一覧
<mt:AssetTags>
:
</mt:AssetTags>
アイテムのタグの一覧
•2つ...
22/122
ブロックタグ(条件判定)
<mt:IfCategory name="cat1">
:
</mt:IfCategory>
カテゴリ名が"cat1"か判定
<mt:AuthorHasEntry>
:
</mt:AuthorHasEnt...
23/122
ブロックタグ(その他:抜粋)
<mt:EntryNext>
:
</mt:EntryNext>
現在の記事のひとつ前の記事を表示
<mt:Entries>
<mt:EntriesHeader>
:
</mt:EntriesHead...
24/122
ブロックタグとファンクションタグの関係
25/122
ブロックタグとファンクションタグの組み合わせ方(繰り返し)
•ブロックタグを単数形にしたファンクションタグが使える
•上の例で、10記事投稿されていれば10回繰り返し
<mt:Entries>
<$mt:EntryTitle$>
...
26/122
ブロックタグとファンクションタグの組み合わせ方(関連オブ
ジェクト)
後半のオブジェクト名のファンクションタグが使える
<mt:EntryAssets>
<$mt:AssetURL$>
</mt:EntryAssets>
27/122
ブロックタグとファンクションタグの組み合わせ方(条件判定)
基本的に前半のオブジェクト名のファンクションタグが使える(はず)
<mt:AuthorHasEntry>
<$mt:AuthorName$>
</mt:AuthorHas...
28/122
問題:記事のカテゴリを出力したい
<mt:Entries>
<$mt:CategoryLabel$>
</mt:Entries>
29/122
データベースとテンプレートタグ
30/122
テンプレートタグの役割
MTに保存したDBのデータを出力する
DBのテーブルやフィールドと対応している
つまり
31/122
データベースとブロックタグの関係(1/2)
<mt:Assets>
<mt:Authors>
<mt:Blogs>
<mt:Categories>
<mt:Comments>
<mt:Entries>
32/122
データベースとブロックタグの関係(2/2)
すべてのオブジェクトがブロックタグになっていない
33/122
データベースとファンクションタグの関係(1/2)
<$mt:EntryID$>
<$mt:EntryBasename$>
<$mt:EntryClass$>
<$mt:EntryExcerpt$>
<$mt:EntryBody$>...
34/122
データベースとファンクションタグの関係(2/2)
すべてのフィールドがファンクションタグになっていない
35/122
テンプレートタグその他
36/122
WordPressテンプレートタグとの違い
↑のような便利タグはないが
MTは前述の規則性を覚えれば
他のオブジェクトへの応用が可能
<?php wp_list_categories( $args );?>
WordPressMo...
37/122
モディファイア
38/122
モディファイアとは
•データの絞り込み条件を指定(ブロックタグ)
•出力データの加工(ファンクションタグ)
39/122
モディファイアのフォーマット
タグ名の後方に「キー="値"」で記述
<mt:Entries xxx="yyy">
:
</mt:Entries>
<mt:EntryTitle xxx="yyy">
ブロックタグファンクションタグ
40/122
モディファイアの種類
•ローカルモディファイア:テンプレートタグ固有のもの
•グローバルモディファイア:全テンプレートタグ共通
グローバルモディファイア
http://www.movabletype.jp/documentatio...
41/122
グローバルモディファイアの数
いくつでも記述可能
<mt:BlogName cat="a" cat="b" cat="c">
42/122
グローバルモディファイアの処理順序
左側から処理
<mt:BlogName cat="a" cat="b" cat="c">
<mt:BlogName cat="c" cat="b" cat="a">
ブログ名が「First We...
43/122
コンテキスト
44/122
コンテキストの意味
状況文脈
45/122
ポイント
テンプレートタグはコンテキストに支配されている
46/122
コンテキストのイメージ
<body>
<div>
<mt:EntryTitle>
<mt:EntryBody>
</div>
</body>
ブログ記事テンプレート
ブログ記事
コンテキスト
<body>
<div>
<mt:En...
47/122
コンテキストエラー
インデックステンプレート
<$mt:EntryTitle$>
48/122
コンテキストの関係
インデックスコンテキスト
アーカイブコンテキスト
テンプレートのコンテキスト
テンプレートタグのコンテキスト
テンプレートタグのコンテキスト
49/122
インデックスコンテキスト
•インデックステンプレートが対象
•ニュートラルなコンテキスト。例えばMTEntriesタグでブロ
グ記事一覧を表示すると、ブログに投稿されたすべてのブ
ログ記事が出力対象。
•コンテキストに依存するデー...
50/122
アーカイブコンテキスト
•アーカイブテンプレートが対象
•アーカイブの種類でコンテキストが決まる。カテゴリアーカイブ
はカテゴリコンテキスト。
ex. MTCategoryLabelタグをブロックタグなしで利用可能
•トップレベル...
51/122
テンプレートタグのコンテキスト(1/2)
•テンプレートの中でブロックタグを記述することでコンテキス
トが切り替わる。
•インデックステンプレートでMTEntriesタグを記述するとブ
ロック内がブログ記事コンテキストになる。
<...
52/122
テンプレートタグのコンテキスト(2/2)
<mt:Entries>
<mt:Comments>
:
</mt:Comments>
</mt:Entries>
ただし親コンテキスト(親テンプレートや親テンプレートタグ)に
依存。
さ...
53/122
コンテキストに依存しないテンプレートタグ
•システム系テンプレートタグ
→ MTVersionタグ、MTPublishCharsetタグなど
•制御系テンプレートタグ
→後述
54/122
制御系テンプレートタグ
55/122
制御系テンプレートタグとは
プログラミング可能な汎用テンプレートタグ
56/122
制御系テンプレートタグの種類
•データを変数※に保持
•変数の取得
•変数の計算
•変数やテンプレートタグの判定
•変数などによる繰り返し処理
•その他
※値を保持するための箱
57/122
変数タグのサンプル1
<$mt:var name="foo" value="1"$>
MTSetVarタグで変数fooに"1"を保持
<$mt:var name="foo"$>
MTSetVarタグで変数fooの値を出力
<$mt...
58/122
変数タグのサンプル2
変数はモディファイアの値として利用可能
<$mt:var name="sort" value="title"$>
<mt:Entries sort_by="$sort">
<mt:EntryTitle>
</...
59/122
変数タグのサンプル3
<mt:SetVarBlock name="foo">1</mt:SetVarBlock>
MTSetVarBlockタグで変数fooに"1"を設定
<mt:SetHashVar name="week">
<...
60/122
変数タグのサンプル4
<mt:SetVars>
foo=1
bar=2
entry_title=<$mt:EntryTitle$>
</mt:SetVars>
MTSetVarsタグで変数と値をまとめて設定
61/122
変数タグのサンプル5
<$mt:var name="foo[0]" value="1"$>
<$mt:var name="foo[1]" value="2"$>
<$mt:var name="foo[2]" value="3"$>...
62/122
変数タグのサンプル6
<$mt:var name="bar{x}" value="a"$>
<$mt:var name="bar{y}" value="b"$>
<$mt:var name="bar{z}" value="c"$>...
63/122
変数タグのサンプル7
<$mt:var name="foo" index="0" value="1"$>
<$mt:var name="foo" index="1" value="2"$>
<$mt:var name="foo" ...
64/122
変数タグのサンプル8
<$mt:SetVar name="foo" op="+" value="5"$>
<$mt:SetVar name="foo" op="-" value="2"$>
<$mt:SetVar name="fo...
65/122
変数タグのサンプル9
<$mt:var name="foo" op="+" value="5"$>
<$mt:var name="foo" op="-" value="2"$>
<$mt:var name="foo" op="*"...
66/122
変数タグのサンプル10
<$mt:var name="count(bar)"$>
ハッシュ変数barの要素数を求める
<$mt:var name="delete(bar)" key="x"$>
ハッシュ変数barから要素を削除
67/122
変数名のハイフンについて
<$mt:var name="foo-1" value="1"$>
変数名にハイフン"-"の使用は控えること
<$mt:var name="foo_1" value="1"$>
<$mt:var name...
68/122
変数名にハイフンが使用できない理由
<$mt:var name="sort-1" value="title"$>
<mt:Entries sort_by="$sort-1">
<mt:EntryTitle>
</mt:Entrie...
69/122
判定文のサンプル1
<mt:if name="foo" eq="1">
OK
<mt:else>
NG
</mt:if>
変数fooが"1"であればOKを出力、そうでなければNGを出力
70/122
判定文のサンプル2
<mt:if name="foo" eq="1">
OK
<mt:elseif name="bar" eq="1">
OK
<mt:else>
NG
</mt:if>
変数fooが"1"であればOKを出力、そう...
71/122
判定文のサンプル3
<mt:unless name="foo" eq="1">
OK
<mt:else>
NG
</mt:unless>
変数fooが"1"でなければOKを出力、そうでなければNGを出力
72/122
判定文のサンプル4
<mt:if name="foo" op="+" value="5" eq="10">
:
</mt:if>
演算($nameの値は変わらず、計算結果を判定)
73/122
繰り返し文のサンプル1
<mt:for var="x" from="0" to="2">
<$mt:var name="foo[$x]"$>
</mt:for>
MTForタグ+配列変数fooで繰り返して配列変数fooの値を出力
74/122
繰り返し文のサンプル2
<mt:loop name="foo">
<$mt:var name="__value__"$>
</mt:loop>
MTLoopタグ+配列変数fooで繰り返し
__value__:配列やハッシュの値を出...
75/122
繰り返し文のサンプル3
<mt:loop name="bar">
<$mt:var name="__key__"$>
<$mt:var name="__value__"$>
</mt:loop>
MTLoopタグ+ハッシュ変数ba...
76/122
MTSetVarTemplateタグでテンプレートの共通化
<mt:SetVarTemplate name="entry">
<$mt:EntryTitle$>:<$mt:EntryBody$>
</mt:SetVarTempla...
77/122
Tips
78/122
テンプレートタグやHTMLの一部を出力しない
<mt:ignore>
<body>
<mt:Entries>
:
</mt:Entries>
</body>
</mt:ignore>
再構築時に評価されない
79/122
繰り返し処理でデータの有無を判定する
<mt:Entries>
:
<mt:else>
:
</mt:Entries>
記事が1件もない場合は
elseブロックを実行
80/122
ページの空白を削除
<mt:Unless name="compress" regex_replace="/^¥s*¥n/gm","">
:
</mt:Unless>
参考:
Movable Type で出力するテンプレートから空行...
81/122
出力データの加工
<mt:EntryTitle regex_replace="/foo/g","bar">
•記事タイトルの中にあるfooをすべてbarに変更
•正規表現の利用が可能
さらに参考:
クォーテーションが含まれたときの...
82/122
if文の判定でPerlを利用
<$mt:setvar name="bar" value="10"$>
<mt:if test="$bar > 5">
<$mt:getvar name="bar"$>
</mt:if>
MTSetV...
83/122
記事本文に記述したテンプレートタグを評価
<mt:EntryBody mteval="1">
記事本文に記述したMTタグを
テンプレートタグとして評価
84/122
テンプレートタグに直接テンプレートタグを設定する
<mt:EntryTitle cat="<$mt:EntryKeywords$>" mteval="1" />
mtevalを使うことで、テンプレートタグのモディファイ
アに直接テ...
85/122
テンプレート上でテンプレートタグを生成する(1/2)
参考:
MTQ - mtタグ内でのPHP使用につきまして
http://communities.movabletype.jp/2012/11/mtphp.html
The bl...
86/122
テンプレート上でテンプレートタグを生成する(2/2)
カスタムフィールドのテンプレートタグを100個生成
MTSample1
MTSample2
MTSample3
:
MTSample10
0
<mt:Entries>
<mt:...
87/122
ブロックタグの省略記法
<$mt:EntryID setvar="entry_id"$>
<mt:Entries id="$entry_id" />
<mt:Entries unique="1" lastn="10">
<$mt:...
88/122
アーカイブページでメインページと同じ内容の「ブログ記事一覧」を表示
アーカイブページで、メインページと同じ内容の「最近のブログ記事一覧」を表示したい場合、
アーカイブコンテキストをインデックスコンテキストや別のコンテキストに変更す...
89/122
ハッシュの入れ子
<mt:SetHashVar name="week">
<$mt:SetVar name="mon" value="Monday"$>
<mt:SetHashVar name="ampm">
<$mt:SetVa...
90/122
自作テンプレートタグ関連プラグイン
91/122
Objectプラグイン
http://www.koikikukan.com/archives/2010/11/09-005555.php
<mt:Objects name="log">
<mt:Object name="log" ...
92/122
Splitプラグイン
http://www.koikikukan.com/archives/2009/01/20-015555.php
<mt:setvar name="foo" value="a AND b AND c" />
...
93/122
GetArchivesプラグイン
http://www.koikikukan.com/archives/2009/01/20-015555.php
<ul><$mt:GetArchives type="monthly"$></ul...
94/122
MultiCalendarプラグイン
http://www.koikikukan.com/archives/2009/01/20-015555.php
<mt:MultiCalendar blog_id="1">
<mt:Cale...
95/122
MondayCalendarプラグイン
http://www.koikikukan.com/archives/2011/06/17-005555.php
<mt:MondayCalendar>
<mt:CalendarWeekHe...
96/122
DateUsecプラグイン
http://www.koikikukan.com/archives/2014/06/16-015555.php
<$mt:DateUsec format="%Y-%m-%d %H:%m:%S."$>
...
97/122
拡張テンプレートタグプラグインの作り方
98/122
プラグインの概要
ブログのテンプレート一覧を出力するMTTemplatesタグと
テンプレート名を出力するMTTemplateNameを提供
<mt:Templates>
<$mt:TemplateName$>
</mt:Temp...
99/122
プラグインファイル構成
plugins/
Templates/
config.yaml
lib/
Templates/
Tags.pm
100/122
config.yaml
name: Templates
id: Templates
description: This plugin is an example plugin.
version: 0.01
tags:
block...
101/122
Tags.pm
package Templates::Tags;
use strict;
sub _hdlr_templates {
my ($ctx, $args, $cond) = @_;
my ($terms, $args...
102/122
プログラム
103/122
主な登場人物
MT::WeblogPublisher
MT::Template
MT::Template::Context
MT::Builder
:再構築を司るクラス
:テンプレートオブジェクト
:タグハンドラの全実装※
:テ...
104/122
テンプレートが再構築される仕組み(イメージ)
xxテンプレート
テンプレートの中身をパース(MT::Builder->compile())
上から順に評価(MT::Builder->build())
トークンリスト
タグハンドラ...
105/122
テンプレートが再構築される仕組み(インデックステンプレート)
sub rebuild_indexes {
$tmpl->build($ctx); # MT::Template
記事投稿・
再構築など
sub build {
my...
106/122
トークン分割とは
・プログラムが読みやすい形式に変換
・DOMのようなもの
my $build = MT::Builder->new;
my $ctx = MT::Template::Context->new;
my $toke...
107/122
トークン分割のサンプル1
my $build = MT::Builder->new;
my $ctx = MT::Template::Context->new;
my $tokens = $build->compile($ctx...
108/122
トークン分割のサンプル2
my $build = MT::Builder->new;
my $ctx = MT::Template::Context->new;
my $tokens = $build->compile($ctx...
109/122
トークン分割のサンプル3
my $build = MT::Builder->new;
my $ctx = MT::Template::Context->new;
my $tokens = $build->compile($ctx...
110/122
トークン分割のサンプル4
my $build = MT::Builder->new;
my $ctx = MT::Template::Context->new;
my $tokens = $build->compile($ctx...
111/122
トークン分割のサンプル5
my $build = MT::Builder->new;
my $ctx = MT::Template::Context->new;
my $tokens = $build->compile($ctx...
112/122
トークン分割のサンプル6
my $build = MT::Builder->new;
my $ctx = MT::Template::Context->new;
my $tokens = $build->compile($ctx...
113/122
トークン分割のサンプル7
my $build = MT::Builder->new;
my $ctx = MT::Template::Context->new;
my $tokens = $build->compile($ctx...
114/122
トークン分割のサンプル8
my $build = MT::Builder->new;
my $ctx = MT::Template::Context->new;
my $tokens = $build->compile($ctx...
115/122
テンプレートタグはどこで識別されているか
sub compile {
:
while ( $text
=~ m!(<¥$?(MT:?)((?:<[^>]+?>|"(?:<[^>]+?>|.)*?"|'(?:<[^>]+?>|.)...
116/122
トークンのビルドとは
・テキストノードの場合、内容の出力
・テンプレートタグの場合、タグハンドラの実行
117/122
sub build {
:
for my $t (@$tokens) {
:
my $hdlr = $ctx->handler_for( $t->tag );
:
my $out = $hdlr->invoke( $ctx, ¥...
118/122
トークンの引き継ぎ
sub build {
for my $t (@$tokens) {
my ( $tokens, $tokens_else, $uncompiled );
if ( $childNodes && ref($c...
119/122
ブロックタグのビルド
ブロックタグの場合、タグハンドラ内でさらにビルドを再帰的に実行し、出力結果を積み上げ
sub build {
:
for my $t (@$tokens) {
:
my $hdlr = $ctx->hand...
120/122
コンテキストエラーの仕組み
記事コンテキストの場合
sub _hdlr_entry_title {
my ( $ctx, $args ) = @_;
my $e = $ctx->stash('entry')
or return ...
121/122
コンテキストエラーの仕組み
記事コンテキストでない場合
<mt:EntryTitle>
インデックステンプレート
sub _no_entry_error {
my ($ctx) = @_;
my $tag_name = $ctx...
122/122
ご静聴ありがとうございました
Upcoming SlideShare
Loading in …5
×

MovableTypeテンプレートタグのまとめ

4,707 views

Published on

MTDDC Meetup Tokyo 2015で発表した「テンプレートタグのまとめ」のスライドです。

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,707
On SlideShare
0
From Embeds
0
Number of Embeds
1,234
Actions
Shares
0
Downloads
12
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

MovableTypeテンプレートタグのまとめ

  1. 1. 1/122 テンプレートタグのまとめ
  2. 2. 2/122 プロフィール
  3. 3. 3/122 テンプレートタグの基礎
  4. 4. 4/122 テンプレートタグとは •MTのテンプレートなどに記述するタグ(MTML) •主にMTに保存したデータを出力 •HTML などのマークアップ言語に似たフォーマット •「ファンクションタグ」と「ブロックタグ」の2種類 •モディファイアもあり
  5. 5. 5/122 テンプレートタグを使った簡単なサンプル1 ブログ名をindex.htmlに出力 インデックステンプレート First Weblog ブログ全般設定画面 再構築 index.html <$mt:BlogName$>
  6. 6. 6/122 テンプレートタグを使った簡単なサンプル2 投稿記事のタイトル・本文を index.htmlに出力 インデックステンプレート ブログ記事投稿画面 テスト1 テスト1です。 テスト2 テスト2です。 index.html再構築 <mt:Entries> <$mt:EntryTitle$><br /> <$mt:EntryBody$><br /> </mt:Entries>
  7. 7. 7/122 管理画面とテンプレートタグの対応1 記事投稿画面 <$mt:EntryTitle$> <$mt:EntryBody$> <mt:EntryTags> <$mt:EntryExcerpt$> <$mt:EntryDate$> <$mt:EntryStatus$> <$mt:EntryBasename$>
  8. 8. 8/122 管理画面とテンプレートタグの対応2 記事一覧画面 <mt:Entries>
  9. 9. 9/122 フォーマット
  10. 10. 10/122 共通的なフォーマット <mt:XXXXX> •ブラケット"<"と">"で括る •"mt:"という接頭辞をつける <mtXXXXX> <MT:XXXXX> <MtXXXXX> 上記でもOK
  11. 11. 11/122 ファンクションタグ
  12. 12. 12/122 ファンクションタグとは •データの属性(ブログID、記事タイトルなど)を出力 •ブロックタグの中に記述しないと動作しないものがある (そうでないものも多数) →詳しくは「コンテキスト」の章で
  13. 13. 13/122 ファンクションタグのフォーマット <$mt:EntryTitle$> <$mt:XXXXX$> 基本的に名称の前半がオブジェクト、後半が属性 タグの先頭と末尾に$をつける(なしでもOK)
  14. 14. 14/122 ファンクションタグのオブジェクト(抜粋) <$mt:Entryxxxx$> <$mt:Pagexxxx$> <$mt:Categoryxxxx$> <$mt:Assetxxxx$> <$mt:Commentxxxx$ > <$mt:Authorxxxx$> <$mt:Blogxxxx$> <$mt:Websitexxxx$> オブジェクト データの属性
  15. 15. 15/122 ファンクションタグの属性(抜粋) <$mt:xxxxName$> <$mt:xxxxLabel$> <$mt:xxxxTitle$> <$mt:xxxxURL$> <$mt:xxxxCount$> <$mt:xxxxID$> <$mt:xxxxLink$> <$mt:xxxxDate$> オブジェクト名 データの属性 名前 ラベル タイトル URL カウント ID リンク 日付
  16. 16. 16/122 ブロックタグ
  17. 17. 17/122 ブロックタグのフォーマット <mt:XXXX> : </mt:XXXX> •開始タグと終了タグを書く •HTMLと同様、終了タグは"/"をつける •ブロックに挟まれた部分を処理する 開始タグ 終了タグ ブロック
  18. 18. 18/122 ブロックタグの種類 <mt:Entries> : </mt:Entries> 主に「繰り返し」「関連オブジェクト」「条件判定」の3種類 <mt:EntryAssets> : </mt:EntryAssets> 繰り返し 関連オブジェクト <mt:IfCategory> : </mt:IfCategory> 条件判定
  19. 19. 19/122 ブロックタグ(繰り返し) <mt:Entries> : </mt:Entries> ブログ記事の繰り返し <mt:Assets> : </mt:Assets> アイテムの繰り返し <mt:Blogs> : </mt:Blogs> ブログの繰り返し •MTのオブジェクト(次スライド)を指定 •必ず複数形で記述
  20. 20. 20/122 ブロックタグに書ける主なオブジェクト ユーザー トラックバック フォルダ タグ アイテム ウェブページ ブログ記事 Websitesウェブサイト ブロックタグオブジェクト カテゴリ ブログ Authors Pings Folders Categories Tags Assets Pages Entries Blogs
  21. 21. 21/122 ブロックタグ(関連オブジェクト) <mt:EntryAssets> : </mt:EntryAssets> ブログ記事のアイテムの一覧 <mt:AssetTags> : </mt:AssetTags> アイテムのタグの一覧 •2つのオブジェクトを併記 •前が親オブジェクト、後が子オブジェクト •ブロック内で子オブジェクトの情報を出力したいとき
  22. 22. 22/122 ブロックタグ(条件判定) <mt:IfCategory name="cat1"> : </mt:IfCategory> カテゴリ名が"cat1"か判定 <mt:AuthorHasEntry> : </mt:AuthorHasEntry> MTユーザーが公開記事を投稿しているか判定 •条件が真であればブロック内を実行 •テンプレートタグ名にIs/Hasといったキーワードあり
  23. 23. 23/122 ブロックタグ(その他:抜粋) <mt:EntryNext> : </mt:EntryNext> 現在の記事のひとつ前の記事を表示 <mt:Entries> <mt:EntriesHeader> : </mt:EntriesHeader> <mt:Entries> 記事一覧で繰り返しの初回のみブロック内を実行
  24. 24. 24/122 ブロックタグとファンクションタグの関係
  25. 25. 25/122 ブロックタグとファンクションタグの組み合わせ方(繰り返し) •ブロックタグを単数形にしたファンクションタグが使える •上の例で、10記事投稿されていれば10回繰り返し <mt:Entries> <$mt:EntryTitle$> </mt:Entries>
  26. 26. 26/122 ブロックタグとファンクションタグの組み合わせ方(関連オブ ジェクト) 後半のオブジェクト名のファンクションタグが使える <mt:EntryAssets> <$mt:AssetURL$> </mt:EntryAssets>
  27. 27. 27/122 ブロックタグとファンクションタグの組み合わせ方(条件判定) 基本的に前半のオブジェクト名のファンクションタグが使える(はず) <mt:AuthorHasEntry> <$mt:AuthorName$> </mt:AuthorHasEntry>
  28. 28. 28/122 問題:記事のカテゴリを出力したい <mt:Entries> <$mt:CategoryLabel$> </mt:Entries>
  29. 29. 29/122 データベースとテンプレートタグ
  30. 30. 30/122 テンプレートタグの役割 MTに保存したDBのデータを出力する DBのテーブルやフィールドと対応している つまり
  31. 31. 31/122 データベースとブロックタグの関係(1/2) <mt:Assets> <mt:Authors> <mt:Blogs> <mt:Categories> <mt:Comments> <mt:Entries>
  32. 32. 32/122 データベースとブロックタグの関係(2/2) すべてのオブジェクトがブロックタグになっていない
  33. 33. 33/122 データベースとファンクションタグの関係(1/2) <$mt:EntryID$> <$mt:EntryBasename$> <$mt:EntryClass$> <$mt:EntryExcerpt$> <$mt:EntryBody$> <$mt:EntryTitle$>
  34. 34. 34/122 データベースとファンクションタグの関係(2/2) すべてのフィールドがファンクションタグになっていない
  35. 35. 35/122 テンプレートタグその他
  36. 36. 36/122 WordPressテンプレートタグとの違い ↑のような便利タグはないが MTは前述の規則性を覚えれば 他のオブジェクトへの応用が可能 <?php wp_list_categories( $args );?> WordPressMovableType <mt:TopLevelCategories> <mt:SubCatIsFirst> <ul> </mt:SubCatIsFirst> <mt:if tag="CategoryCount"> <li><a href="<$mt:CategoryArchiveLink$>"> <$mt:CategoryLabel$>(<$mt:CategoryCount$>)</a> <mt:else> <li><$mt:CategoryLabel$> </mt:if> <$mt:SubCatsRecurse$> </li> <mt:SubCatIsLast> </ul> </mt:SubCatIsLast> </mt:TopLevelCategories>
  37. 37. 37/122 モディファイア
  38. 38. 38/122 モディファイアとは •データの絞り込み条件を指定(ブロックタグ) •出力データの加工(ファンクションタグ)
  39. 39. 39/122 モディファイアのフォーマット タグ名の後方に「キー="値"」で記述 <mt:Entries xxx="yyy"> : </mt:Entries> <mt:EntryTitle xxx="yyy"> ブロックタグファンクションタグ
  40. 40. 40/122 モディファイアの種類 •ローカルモディファイア:テンプレートタグ固有のもの •グローバルモディファイア:全テンプレートタグ共通 グローバルモディファイア http://www.movabletype.jp/documentation/appendices/modifiers/ ※ローカルモディファイアは各テンプレートタグリファレンスに記載
  41. 41. 41/122 グローバルモディファイアの数 いくつでも記述可能 <mt:BlogName cat="a" cat="b" cat="c">
  42. 42. 42/122 グローバルモディファイアの処理順序 左側から処理 <mt:BlogName cat="a" cat="b" cat="c"> <mt:BlogName cat="c" cat="b" cat="a"> ブログ名が「First Weblog」の場合、「 First Weblogabc」 ブログ名が「First Weblog」の場合、「 First Weblogcba」
  43. 43. 43/122 コンテキスト
  44. 44. 44/122 コンテキストの意味 状況文脈
  45. 45. 45/122 ポイント テンプレートタグはコンテキストに支配されている
  46. 46. 46/122 コンテキストのイメージ <body> <div> <mt:EntryTitle> <mt:EntryBody> </div> </body> ブログ記事テンプレート ブログ記事 コンテキスト <body> <div> <mt:Entries> : </mt:Entries> <mt:Categories> : <mt:Categories> </div> </dody> ブログ記事 コンテキスト インデックステンプレート テンプレートのコンテキスト テンプレートタグのコンテキスト カテゴリ コンテキスト
  47. 47. 47/122 コンテキストエラー インデックステンプレート <$mt:EntryTitle$>
  48. 48. 48/122 コンテキストの関係 インデックスコンテキスト アーカイブコンテキスト テンプレートのコンテキスト テンプレートタグのコンテキスト テンプレートタグのコンテキスト
  49. 49. 49/122 インデックスコンテキスト •インデックステンプレートが対象 •ニュートラルなコンテキスト。例えばMTEntriesタグでブロ グ記事一覧を表示すると、ブログに投稿されたすべてのブ ログ記事が出力対象。 •コンテキストに依存するデータを出力したい場合、ブロック タグで該当のコンテキストに切り替える。
  50. 50. 50/122 アーカイブコンテキスト •アーカイブテンプレートが対象 •アーカイブの種類でコンテキストが決まる。カテゴリアーカイブ はカテゴリコンテキスト。 ex. MTCategoryLabelタグをブロックタグなしで利用可能 •トップレベルのテンプレートタグはアーカイブコンテキストに依存。 ex. カテゴリアーカイブでMTEntriesタグを使用すると、該当カテ ゴリの記事に絞られる。 アーカイブテンプレートがテンプレートタグ(MTCategoriesなど)で括られているようなイメージ
  51. 51. 51/122 テンプレートタグのコンテキスト(1/2) •テンプレートの中でブロックタグを記述することでコンテキス トが切り替わる。 •インデックステンプレートでMTEntriesタグを記述するとブ ロック内がブログ記事コンテキストになる。 <mt:Entries> : </mt:Entries> ブログ記事 コンテキスト インデックステンプレート ニュートラル ニュートラル
  52. 52. 52/122 テンプレートタグのコンテキスト(2/2) <mt:Entries> <mt:Comments> : </mt:Comments> </mt:Entries> ただし親コンテキスト(親テンプレートや親テンプレートタグ)に 依存。 さらにMTCommentsタグを記述するとブロック内がコメ ントコンテキストに切り替わる。 コメント コンテキスト ニュートラル ニュートラル ブログ記事 コンテキスト
  53. 53. 53/122 コンテキストに依存しないテンプレートタグ •システム系テンプレートタグ → MTVersionタグ、MTPublishCharsetタグなど •制御系テンプレートタグ →後述
  54. 54. 54/122 制御系テンプレートタグ
  55. 55. 55/122 制御系テンプレートタグとは プログラミング可能な汎用テンプレートタグ
  56. 56. 56/122 制御系テンプレートタグの種類 •データを変数※に保持 •変数の取得 •変数の計算 •変数やテンプレートタグの判定 •変数などによる繰り返し処理 •その他 ※値を保持するための箱
  57. 57. 57/122 変数タグのサンプル1 <$mt:var name="foo" value="1"$> MTSetVarタグで変数fooに"1"を保持 <$mt:var name="foo"$> MTSetVarタグで変数fooの値を出力 <$mt:EntryTitle setvar="entry_title"$> MTEntryTitleタグの内容を変数entry_titleに設定
  58. 58. 58/122 変数タグのサンプル2 変数はモディファイアの値として利用可能 <$mt:var name="sort" value="title"$> <mt:Entries sort_by="$sort"> <mt:EntryTitle> </mt:Entries> <mt:Entries sort_by="title"> <mt:EntryTitle> </mt:Entries> 上のマークアップは下と同じ
  59. 59. 59/122 変数タグのサンプル3 <mt:SetVarBlock name="foo">1</mt:SetVarBlock> MTSetVarBlockタグで変数fooに"1"を設定 <mt:SetHashVar name="week"> <$mt:SetVar name="mon" value="Monday"$> <$mt:SetVar name="tue" value="Tuesday"$> <$mt:SetVar name="wed" value="Wednesday"$> <$mt:SetVar name="thu" value="Thursday"$> <$mt:SetVar name="fri" value="Friday"$> <$mt:SetVar name="sat" value="Satday"$> <$mt:SetVar name="sun" value="Sunday"$> </mt:SetHashVar> MTSetHashVarタグで変数weekにキーと値をまとめて設定
  60. 60. 60/122 変数タグのサンプル4 <mt:SetVars> foo=1 bar=2 entry_title=<$mt:EntryTitle$> </mt:SetVars> MTSetVarsタグで変数と値をまとめて設定
  61. 61. 61/122 変数タグのサンプル5 <$mt:var name="foo[0]" value="1"$> <$mt:var name="foo[1]" value="2"$> <$mt:var name="foo[2]" value="3"$> 配列変数fooに"1","2","3"を設定 <$mt:var name="foo[0]"$> <$mt:var name="foo[1]"$> <$mt:var name="foo[2]"$> 配列変数fooから値を出力
  62. 62. 62/122 変数タグのサンプル6 <$mt:var name="bar{x}" value="a"$> <$mt:var name="bar{y}" value="b"$> <$mt:var name="bar{z}" value="c"$> ハッシュ変数barに"a","b","c"を設定 <$mt:var name="bar{x}"$> <$mt:var name="bar{y}"$> <$mt:var name="bar{z}"$> ハッシュ変数barから値を出力
  63. 63. 63/122 変数タグのサンプル7 <$mt:var name="foo" index="0" value="1"$> <$mt:var name="foo" index="1" value="2"$> <$mt:var name="foo" index="2" value="3"$> 配列変数fooに"1","2","3"を設定(前述のスライドと同じ) <$mt:var name="bar" key="x" value="a"$> <$mt:var name="bar" key="y" value="b"$> <$mt:var name="bar" key="z" value="c"$> ハッシュ変数barに"a","b","c"を設定(前述のスライドと同じ)
  64. 64. 64/122 変数タグのサンプル8 <$mt:SetVar name="foo" op="+" value="5"$> <$mt:SetVar name="foo" op="-" value="2"$> <$mt:SetVar name="foo" op="*" value="3"$> <$mt:SetVar name="foo" op="/" value="2"$> <$mt:SetVar name="foo" op="%" value="2"$> <$mt:SetVar name="foo" op="++"$> <$mt:SetVar name="foo" op="--"$> 演算($nameに計算結果を保存)
  65. 65. 65/122 変数タグのサンプル9 <$mt:var name="foo" op="+" value="5"$> <$mt:var name="foo" op="-" value="2"$> <$mt:var name="foo" op="*" value="3"$> <$mt:var name="foo" op="/" value="2"$> <$mt:var name="foo" op="%" value="2"$> <$mt:var name="foo" op="++"$> <$mt:var name="foo" op="--"$> 演算($nameの値は変わらず、計算結果を出力)
  66. 66. 66/122 変数タグのサンプル10 <$mt:var name="count(bar)"$> ハッシュ変数barの要素数を求める <$mt:var name="delete(bar)" key="x"$> ハッシュ変数barから要素を削除
  67. 67. 67/122 変数名のハイフンについて <$mt:var name="foo-1" value="1"$> 変数名にハイフン"-"の使用は控えること <$mt:var name="foo_1" value="1"$> <$mt:var name="foo1" value="1"$>
  68. 68. 68/122 変数名にハイフンが使用できない理由 <$mt:var name="sort-1" value="title"$> <mt:Entries sort_by="$sort-1"> <mt:EntryTitle> </mt:Entries> 例:MTEntriesのcategoryモディファイアに変数を利用 ※禁止ではない($なしの使い方であればOK) テンプレートとして期待する動作にならない
  69. 69. 69/122 判定文のサンプル1 <mt:if name="foo" eq="1"> OK <mt:else> NG </mt:if> 変数fooが"1"であればOKを出力、そうでなければNGを出力
  70. 70. 70/122 判定文のサンプル2 <mt:if name="foo" eq="1"> OK <mt:elseif name="bar" eq="1"> OK <mt:else> NG </mt:if> 変数fooが"1"であればOKを出力、そうでなければ変数barが1であ ればOKを出力、そうでなければNGを出力
  71. 71. 71/122 判定文のサンプル3 <mt:unless name="foo" eq="1"> OK <mt:else> NG </mt:unless> 変数fooが"1"でなければOKを出力、そうでなければNGを出力
  72. 72. 72/122 判定文のサンプル4 <mt:if name="foo" op="+" value="5" eq="10"> : </mt:if> 演算($nameの値は変わらず、計算結果を判定)
  73. 73. 73/122 繰り返し文のサンプル1 <mt:for var="x" from="0" to="2"> <$mt:var name="foo[$x]"$> </mt:for> MTForタグ+配列変数fooで繰り返して配列変数fooの値を出力
  74. 74. 74/122 繰り返し文のサンプル2 <mt:loop name="foo"> <$mt:var name="__value__"$> </mt:loop> MTLoopタグ+配列変数fooで繰り返し __value__:配列やハッシュの値を出力する特殊変数
  75. 75. 75/122 繰り返し文のサンプル3 <mt:loop name="bar"> <$mt:var name="__key__"$> <$mt:var name="__value__"$> </mt:loop> MTLoopタグ+ハッシュ変数barで繰り返し __key__:ハッシュのキーを出力する特殊変数
  76. 76. 76/122 MTSetVarTemplateタグでテンプレートの共通化 <mt:SetVarTemplate name="entry"> <$mt:EntryTitle$>:<$mt:EntryBody$> </mt:SetVarTemplate> 今日の記事 <mt:Entries lastn="1"> <mt:var name="entry"> </mt:Entries> 最近の記事 <mt:Entries lastn="5" unique="1"> <mt:var name="entry"> </mt:Entries>
  77. 77. 77/122 Tips
  78. 78. 78/122 テンプレートタグやHTMLの一部を出力しない <mt:ignore> <body> <mt:Entries> : </mt:Entries> </body> </mt:ignore> 再構築時に評価されない
  79. 79. 79/122 繰り返し処理でデータの有無を判定する <mt:Entries> : <mt:else> : </mt:Entries> 記事が1件もない場合は elseブロックを実行
  80. 80. 80/122 ページの空白を削除 <mt:Unless name="compress" regex_replace="/^¥s*¥n/gm",""> : </mt:Unless> 参考: Movable Type で出力するテンプレートから空行を削除 したい http://www.tinybeans.net/blog/2012/10/18- 094419.html 空白を削除したい部分を下記で括る
  81. 81. 81/122 出力データの加工 <mt:EntryTitle regex_replace="/foo/g","bar"> •記事タイトルの中にあるfooをすべてbarに変更 •正規表現の利用が可能 さらに参考: クォーテーションが含まれたときの書き方 http://www.mtcms.jp/movabletype-blog/tech/201104222143.html
  82. 82. 82/122 if文の判定でPerlを利用 <$mt:setvar name="bar" value="10"$> <mt:if test="$bar > 5"> <$mt:getvar name="bar"$> </mt:if> MTSetVarタグで作った変数 bar の値が5以上であること を判定し、マッチすれば MTIf タグのブロックを実行
  83. 83. 83/122 記事本文に記述したテンプレートタグを評価 <mt:EntryBody mteval="1"> 記事本文に記述したMTタグを テンプレートタグとして評価
  84. 84. 84/122 テンプレートタグに直接テンプレートタグを設定する <mt:EntryTitle cat="<$mt:EntryKeywords$>" mteval="1" /> mtevalを使うことで、テンプレートタグのモディファイ アに直接テンプレートタグを記述することが可能 <$mt:SetVar name="<$mt:EntryTitle$>" value="<$mt:EntryBody$>" mteval="1"$> 参考: Movable Typeのテンプレートタグの中でテンプレートタグを使う方法 http://www.koikikukan.com/archives/2014/07/08-005555.php
  85. 85. 85/122 テンプレート上でテンプレートタグを生成する(1/2) 参考: MTQ - mtタグ内でのPHP使用につきまして http://communities.movabletype.jp/2012/11/mtphp.html The blog of H.Fujimoto - 実行するテンプレートタグを変数で指定する http://www.h-fj.com/blog/archives/2012/11/13-163510.php <mt:SetVarBlock name="tag">&lt;$mt:EntryTitle$&gt;</mt:SetVarBlock> <$mt:GetVar name="tag" decode_html="1" mteval="1"$>
  86. 86. 86/122 テンプレート上でテンプレートタグを生成する(2/2) カスタムフィールドのテンプレートタグを100個生成 MTSample1 MTSample2 MTSample3 : MTSample10 0 <mt:Entries> <mt:for var="i" from="1" to="100"> <mt:SetVarBlock name="tag">&lt;$mt:Sample<$mt:GetVar name="i"$>$&gt;</mt:SetVarBlock> <$mt:GetVar name="tag" decode_html="1" mteval="1"$> </mt:for> </mt:Entries>
  87. 87. 87/122 ブロックタグの省略記法 <$mt:EntryID setvar="entry_id"$> <mt:Entries id="$entry_id" /> <mt:Entries unique="1" lastn="10"> <$mt:EntryTitle$> </mt:Entries> 参考: ブログ記事ページでその記事以外のブログ記事一覧を表示 する方法 http://www.koikikukan.com/archives/2015/07/30- 005555.php
  88. 88. 88/122 アーカイブページでメインページと同じ内容の「ブログ記事一覧」を表示 アーカイブページで、メインページと同じ内容の「最近のブログ記事一覧」を表示したい場合、 アーカイブコンテキストをインデックスコンテキストや別のコンテキストに変更する。 IndexContextプラグイン ( http://blog.aklaswad.com/mtplugins/indexcontext.html )を利用する ArchiveListタグを使用する Blogsタグにignore_archive_contextモディファイアを利用する<mt:IndexContext> : </mt:IndexContext> <mt:ArchiveList type="Individual" lastn="10"> <$mt:EntryTitle$> </mt:ArchiveList> <mt:Blogs blog_id="2" ignore_archive_context="1"> <mt:Entries blog_id="2" lastn="10"> <$mt:EntryTitle$> </mt:Entries> </mt:Blogs>
  89. 89. 89/122 ハッシュの入れ子 <mt:SetHashVar name="week"> <$mt:SetVar name="mon" value="Monday"$> <mt:SetHashVar name="ampm"> <$mt:SetVar name="am" value="AM"$> <$mt:SetVar name="pm" value="PM"$> </mt:SetHashVar> </mt:SetHashVar> <mt:GetVar name="week{ampm}" setvar="foo" /> <mt:GetVar name="foo{am}" /> MTHashVarタグで入れ子にする 参考: Movable Type の配列とハッシュの入れ子 http://www.koikikukan.com/archives/2009/12/15-005555.php
  90. 90. 90/122 自作テンプレートタグ関連プラグイン
  91. 91. 91/122 Objectプラグイン http://www.koikikukan.com/archives/2010/11/09-005555.php <mt:Objects name="log"> <mt:Object name="log" property="message" /> </mt:Objects> テンプレートタグ化されていないオブジェクトデータをテンプレートで取得 例:ログデータを取得
  92. 92. 92/122 Splitプラグイン http://www.koikikukan.com/archives/2009/01/20-015555.php <mt:setvar name="foo" value="a AND b AND c" /> <mt:getVar name="foo" split=" AND " setvar="bar"> <mt:loop name="bar"> <mt:getVar name="__value__" /><br /> </mt:loop> a b c 変数の値を配列に変換
  93. 93. 93/122 GetArchivesプラグイン http://www.koikikukan.com/archives/2009/01/20-015555.php <ul><$mt:GetArchives type="monthly"$></ul> WordPressの「wp_get_archives」のMT版
  94. 94. 94/122 MultiCalendarプラグイン http://www.koikikukan.com/archives/2009/01/20-015555.php <mt:MultiCalendar blog_id="1"> <mt:CalendarWeekHeader><tr></mt:CalendarWeekHeader> <td> <mt:CalendarIfEntries> <mt:Entries lastn="1"> <a href="<$mt:EntryPermalink$>"><$mt:CalendarDay$></a> </mt:Entries> </mt:CalendarIfEntries> <mt:CalendarIfNoEntries> <$mt:CalendarDay$> </mt:CalendarIfNoEntries> <mt:CalendarIfBlank>&nbsp;</mt:CalendarIfBlank> </td> <mt:CalendarWeekFooter></tr></mt:CalendarWeekFooter> </mt:MultiCalendar> 複数ブログの情報をひとつのカレンダーに表示
  95. 95. 95/122 MondayCalendarプラグイン http://www.koikikukan.com/archives/2011/06/17-005555.php <mt:MondayCalendar> <mt:CalendarWeekHeader><tr></mt:CalendarWeekHeader> <td> <mt:CalendarIfEntries> <mt:Entries lastn="1"> <a href="<$mt:EntryPermalink$>"><$mt:CalendarDay$></a> </mt:Entries> </mt:CalendarIfEntries> <mt:CalendarIfNoEntries> <$mt:CalendarDay$> </mt:CalendarIfNoEntries> <mt:CalendarIfBlank>&nbsp;</mt:CalendarIfBlank> </td> <mt:CalendarWeekFooter></tr></mt:CalendarWeekFooter> </mt:MondayCalendar> カレンダーを月曜始まりに変更
  96. 96. 96/122 DateUsecプラグイン http://www.koikikukan.com/archives/2014/06/16-015555.php <$mt:DateUsec format="%Y-%m-%d %H:%m:%S."$> ミリ秒・マイクロ秒を表示 2014-06-16 01:07:37.580135
  97. 97. 97/122 拡張テンプレートタグプラグインの作り方
  98. 98. 98/122 プラグインの概要 ブログのテンプレート一覧を出力するMTTemplatesタグと テンプレート名を出力するMTTemplateNameを提供 <mt:Templates> <$mt:TemplateName$> </mt:Templates>
  99. 99. 99/122 プラグインファイル構成 plugins/ Templates/ config.yaml lib/ Templates/ Tags.pm
  100. 100. 100/122 config.yaml name: Templates id: Templates description: This plugin is an example plugin. version: 0.01 tags: block: Templates: $Templates::Templates::Tags::_hdlr_templates function: TemplateName: $Templates::Templates::Tags::_hdlr_template_name テンプレート名 タグハンドラ名 テンプレートタグ定義 ブロックタグ定義 ファンクションタグ定義
  101. 101. 101/122 Tags.pm package Templates::Tags; use strict; sub _hdlr_templates { my ($ctx, $args, $cond) = @_; my ($terms, $args); $terms->{ blog_id } = $ctx->stash('blog_id'); $args->{ sort } = 'name'; my $iter = MT::Template->load_iter( $terms, $args ); my $res = ''; my $tokens = $ctx->stash('tokens'); my $builder = $ctx->stash('builder'); while (my $tmpl = $iter->()) { local $ctx->{__stash}{tmpl} = $tmpl; defined(my $out = $builder->build($ctx, $tokens, $cond)) or return $ctx->error( $builder->errstr ); $res .= $out; } $res; } sub _hdlr_template_name { my ($ctx, $args) = @_; my $tmpl = $ctx->stash('tmpl') or return _error($ctx, 'MT'.$ctx->stash('tag')); $tmpl->name; } sub _error { my ($ctx, $tag) = @_; $ctx->error(MT->translate('You used an [_1] tag outside of the proper context.', $tag)); } 1; 正直、意味がわからないw
  102. 102. 102/122 プログラム
  103. 103. 103/122 主な登場人物 MT::WeblogPublisher MT::Template MT::Template::Context MT::Builder :再構築を司るクラス :テンプレートオブジェクト :タグハンドラの全実装※ :テンプレートのパースとインタープリタ ※MT::Template::Tags・アドオン・拡張テンプレートタグなど
  104. 104. 104/122 テンプレートが再構築される仕組み(イメージ) xxテンプレート テンプレートの中身をパース(MT::Builder->compile()) 上から順に評価(MT::Builder->build()) トークンリスト タグハンドラ ・ファンクションタグであればデータを出力 ・ブロックタグであれば内部でビルド ・テキストはそのまま出力 ・テンプレートタグがあればタグハンドラ実行 ブロックタグが なくなるまで 繰り返される トークンリスト(DOMのようなもの)生成
  105. 105. 105/122 テンプレートが再構築される仕組み(インデックステンプレート) sub rebuild_indexes { $tmpl->build($ctx); # MT::Template 記事投稿・ 再構築など sub build { my $ctx = $tmpl->context; # MT::Template::Context->new; my $tokens = $tmpl->compile(); # MT::Builder->compile($tmpl); my $res = $builder->build( $ctx, $tokens, $cond ); # MT::Builder MT::WeblogPublisher sub compile { ... } sub build { ... } MT::Template MT::Builder テンプレートの再構築開始 テンプレートを トークン分割し、 トークンリスト生成 トークンリストから出力ページを作成
  106. 106. 106/122 トークン分割とは ・プログラムが読みやすい形式に変換 ・DOMのようなもの my $build = MT::Builder->new; my $ctx = MT::Template::Context->new; my $tokens = $build->compile($ctx, '<$mt:BlogName$>'); トークン分割のサンプルコード(抜粋)
  107. 107. 107/122 トークン分割のサンプル1 my $build = MT::Builder->new; my $ctx = MT::Template::Context->new; my $tokens = $build->compile($ctx, '<$mt:BlogName$>'); $VAR1 = [ bless( [ 'BlogName', {}, [], undef, [], undef, undef ], 'MT::Template::Node' ) ]; $tokens
  108. 108. 108/122 トークン分割のサンプル2 my $build = MT::Builder->new; my $ctx = MT::Template::Context->new; my $tokens = $build->compile($ctx, '<$mt:BlogName$><$mt:BlogID$><$mt:Version$>'); $VAR1 = [ bless( [ 'BlogName', {}, [], undef, [], undef, undef ], 'MT::Template::Node' ), bless( [ 'BlogID', {}, [], undef, [], undef, undef ], 'MT::Template::Node' ), bless( [ 'Version', {}, [], undef, [], undef, undef ], 'MT::Template::Node' ) ]; $tokens
  109. 109. 109/122 トークン分割のサンプル3 my $build = MT::Builder->new; my $ctx = MT::Template::Context->new; my $tokens = $build->compile($ctx, '<mt:Entries><mt:EntryTitle></mt:Entries>'); $VAR1 = [ bless( [ 'Entries', {}, [ bless( [ 'EntryTitle', {}, [], undef, [], $VAR1->[0], undef ], 'MT::Template::Node' ) ], '<$mt:EntryTitle$>', [], undef, undef ], 'MT::Template::Node' ) ]; $tokens
  110. 110. 110/122 トークン分割のサンプル4 my $build = MT::Builder->new; my $ctx = MT::Template::Context->new; my $tokens = $build->compile($ctx, '<mt:Entries sort="descend"> <mt:EntryTitle> </mt:Entries>'); $VAR1 = [ bless( [ 'Entries', { 'sort' => 'decend' }, [ bless( [ 'EntryTitle', {}, [], undef, [], $VAR1->[0], undef ], 'MT::Template::Node' ) ], '<$mt:EntryTitle$>', [], undef, undef ], 'MT::Template::Node' ) ]; $tokens
  111. 111. 111/122 トークン分割のサンプル5 my $build = MT::Builder->new; my $ctx = MT::Template::Context->new; my $tokens = $build->compile($ctx, '<mt:Entries sort="descend"> <mt:EntryTitle cat="foo"> </mt:Entries>'); $VAR1 = [ bless( [ 'Entries', { 'sort' => 'decend' }, [ bless( [ 'EntryTitle', { 'cat' => 'foo' }, [], undef, [ [ 'cat', 'foo' ] ], $VAR1->[0], undef ], 'MT::Template::Node' ) ], '<$mt:EntryTitle cat="foo"$>', [], undef, undef ], 'MT::Template::Node' ) ]; $tokens
  112. 112. 112/122 トークン分割のサンプル6 my $build = MT::Builder->new; my $ctx = MT::Template::Context->new; my $tokens = $build->compile($ctx, '<mt:Entries> <mt:EntryTitle> <mt:EntryBody> </mt:Entries>'); $VAR1 = [ bless( [ 'Entries', { 'sort' => 'decend' }, [ bless( [ 'EntryTitle', {}, [], undef, [], $VAR1->[0], undef ], 'MT::Template::Node' ), bless( [ 'EntryBody', {}, [], undef, [], $VAR1->[0], undef ], 'MT::Template::Node' ) ], '<$mt:EntryTitle cat="foo"$><$mt:EntryBody$>', [], undef, undef ], 'MT::Template::Node' ) ]; $tokens
  113. 113. 113/122 トークン分割のサンプル7 my $build = MT::Builder->new; my $ctx = MT::Template::Context->new; my $tokens = $build->compile($ctx, '<mt:Entries> <mt:EntryTitle> aaaaa <mt:EntryBody> </mt:Entries>'); $VAR1 = [ bless( [ 'Entries', { 'sort' => 'decend' }, [ bless( [ 'EntryTitle', {}, [], undef, [], $VAR1->[0], undef ], 'MT::Template::Node' ), bless( [ 'TEXT', 'aaaaa', undef, undef, undef, $VAR1->[0][2], undef ], 'MT::Template::Node' ), bless( [ 'EntryBody', {}, [], undef, [], $VAR1->[0], undef ], 'MT::Template::Node' ) ], '<$mt:EntryTitle cat="foo"$>aaaaa<$mt:EntryBody$>', [], undef, undef ], 'MT::Template::Node' ) ]; $tokens
  114. 114. 114/122 トークン分割のサンプル8 my $build = MT::Builder->new; my $ctx = MT::Template::Context->new; my $tokens = $build->compile($ctx, '<$mt:var name="foo" value="1"$> <mt:Entries sort="decend"> <mt:if name="foo" eq="1"> <$mt:EntryTitle cat="foo"$> </mt:if> aaaaa <$mt:EntryBody$> </mt:Entries>'); $VAR1 = [ bless( [ 'var', { 'value' => '1', 'name' => 'foo' }, [], undef, [], undef, undef ], 'MT::Template::Node' ), bless( [ 'Entries', { 'sort' => 'decend' }, [ bless( [ 'if', { 'name' => 'foo', 'eq' => '1' }, [ bless( [ 'EntryTitle', {}, [], undef, [], $VAR1->[1][2][0], undef ], 'MT::Template::Node' ) ], '<$mt:EntryTitle cat="foo"$>', [], $VAR1->[1], undef ], 'MT::Template::Node' ), bless( [ 'TEXT', 'aaaaa', undef, undef, undef, $VAR1->[1][2], undef ], 'MT::Template::Node' ), bless( [ 'EntryBody', {}, [], undef, [], $VAR1->[1], undef ], 'MT::Template::Node' ) ], '<mt:if name="foo" eq="1"><$mt:EntryTitle cat="foo"$></mt:if>aaaaa<$mt:EntryBody$>', [], undef, undef ], 'MT::Template::Node' ) ]; $tokens
  115. 115. 115/122 テンプレートタグはどこで識別されているか sub compile { : while ( $text =~ m!(<¥$?(MT:?)((?:<[^>]+?>|"(?:<[^>]+?>|.)*?"|'(?:<[^>]+?>|.)*?'|.)+?)([-]?)[¥$/]?>)!gis ) { my ( $whole_tag, $prefix, $tag, $space_eater ) = ( $1, $2, $3, $4 ); : MT::Builder $whole_tag:<mt:Entries sort_by="title"> $prefix:mt: $tag:entries sort_by="title"
  116. 116. 116/122 トークンのビルドとは ・テキストノードの場合、内容の出力 ・テンプレートタグの場合、タグハンドラの実行
  117. 117. 117/122 sub build { : for my $t (@$tokens) { : my $hdlr = $ctx->handler_for( $t->tag ); : my $out = $hdlr->invoke( $ctx, ¥%args, $cond ); : } } トークンのビルドイメージ MT::Builder $VAR1 = [ bless( [ 'BlogName', {}, [], undef, [], undef, undef ], 'MT::Template::Node' ), bless( [ 'BlogID', {}, [], undef, [], undef, undef ], 'MT::Template::Node' ), bless( [ 'Version', {}, [], undef, [], undef, undef ], 'MT::Template::Node' ) ]; 繰り返し1回目 繰り返し2回目 繰り返し3回目 ③タグハンドラの実行 ②タグハンドラ(MT::Template::Handler)を 返却。$tは分割したトークン ①$tokensのリスト分繰り返し
  118. 118. 118/122 トークンの引き継ぎ sub build { for my $t (@$tokens) { my ( $tokens, $tokens_else, $uncompiled ); if ( $childNodes && ref($childNodes) ) { ( $tokens, $tokens_else ) = ( [], [] ); for my $sub (@$childNodes) { my $tag = lc $sub->tag; if ( $tag eq 'else' || $tag eq 'elseif' ) { push @$tokens_else, $sub; } else { push @$tokens, $sub; } } my $hdlr = $ctx->handler_for( $t->tag ); my ( $h, $type, $orig ) = $hdlr->values; my $conditional = defined $type && $type == 2; if ($h) { $timer->pause_partial if $timer; local ( $ctx->{__stash}{tag} ) = $t->tag; local ( $ctx->{__stash}{tokens} ) = ref($tokens) ? bless $tokens, 'MT::Template::Tokens' : undef; local ( $ctx->{__stash}{tokens_else} ) = ref($tokens_else) ? bless $tokens_else, 'MT::Template::Tokens' : undef; local ( $ctx->{__stash}{uncompiled} ) = $uncompiled; ①子ノードがあれば $tokensまたは $tokens_elseにpush ②子ノードの$tokensを $ctx(stash)に 保持(=引き継ぎ) MT::Builder $VAR1 = [ bless( [ 'Entries', {}, [ bless( [ 'EntryTitle', {}, [], undef, [], $VAR1->[0], undef ], 'MT::Template::Node' ) ], '<$mt:EntryTitle$>', [], undef, undef ], 'MT::Template::Node' ) ]; 子 ノ ー ド 親 ノ ー ド
  119. 119. 119/122 ブロックタグのビルド ブロックタグの場合、タグハンドラ内でさらにビルドを再帰的に実行し、出力結果を積み上げ sub build { : for my $t (@$tokens) { : my $hdlr = $ctx->handler_for( $t->tag ); : my $out = $hdlr->invoke( $ctx, ¥%args, $cond ); : } } MT::Builder sub _hdlr_entries { : my $tok = $ctx->stash('tokens'); : for my $e (@entries) { : my $out = $builder->build( $ctx, $tok, ... ); : } } ②ブロックタグがあればビルドを再帰的に実行 MT::Template::Tag::Entry ①タグハンドラ実行
  120. 120. 120/122 コンテキストエラーの仕組み 記事コンテキストの場合 sub _hdlr_entry_title { my ( $ctx, $args ) = @_; my $e = $ctx->stash('entry') or return $ctx->_no_entry_error(); my $title = defined $e->title ? $e->title : ''; : return $title; } sub _hdlr_entries { : for my $e (@entries) { : local $ctx->{__stash}{entry} = $e; : my $out = $builder->build( $ctx, $tok, ... ); : } } <mt:Entries> <mt:EntryTitle> </mt:Entries> インデックステンプレート MT::Template::Tag::Entry MT::Template::Tag::Entry ①MTEntriesタグの処理で 記事コンテキストを設定 ②MTEntryTitleタグ内のコンテキスト判定OK
  121. 121. 121/122 コンテキストエラーの仕組み 記事コンテキストでない場合 <mt:EntryTitle> インデックステンプレート sub _no_entry_error { my ($ctx) = @_; my $tag_name = $ctx->stash('tag'); $tag_name = 'mt' . $tag_name unless $tag_name =~ m/^MT/i; return $_[0]->error( MT->translate( "You used an '[_1]' tag outside of the context of an entry; " . "Perhaps you mistakenly placed it outside of an 'MTEntries' container tag?", $tag_name ) ); } MT::Template::Context ①いきなりMTEntryTitleタグ処理のため、 記事コンテキスト判定NG ②エラー処理 sub _hdlr_entry_title { my ( $ctx, $args ) = @_; my $e = $ctx->stash('entry') or return $ctx- >_no_entry_error(); my $title = defined $e->title ? $e- >title : ''; : return $title; } MT::Template::Tag::Entry
  122. 122. 122/122 ご静聴ありがとうございました

×