PHPerのための Movable Type 講座(その5)
公開日 : 2014-04-16 13:01:55
暖かくなりましたね。続きます。
- PHPerのための Movable Type 講座(その1)
- PHPerのための Movable Type 講座(その2)
- PHPerのための Movable Type 講座(その3)
- PHPerのための Movable Type 講座(その4)
class MTViewer( extends Smarty) 編。$ctxです。そう、コンテキストはSmartyであるのですが、今日はこれ。テンプレートエンジンの謎を探る(謎というわけでもないが)。PHPでのMTタグの作り方です。
公式ドキュメントは以下。
公式ドキュメントではPerl(スタティック)の解説が前半、後半がPHPになっていますが、基本的にはタグの作成方法についてのドキュメントではPHPについても言及されています。
ベースにするのは昨日の以下のコード。当面「生」PHPで行くことにします。そろそろプラグインに行きたいところであるけれども。
この例では、「生」PHPですが、MTのお作法に従ってプラグインとして作る場合も基本は一緒です。$ctxのメソッドで動的にタグが登録しているという違いがあるだけで、基本は同じです。
<?php
$blog_id = 1;
include('/path/to/mt/php/mt.php');
$mt = MT::get_instance( $blog_id, '/path/to/mt/mt-config.cgi' );
$ctx =& $mt->context();
$ctx->caching = FALSE;
$blog = $mt->db()->fetch_blog( $blog_id );
$ctx->stash( 'blog', $blog );
$ctx->stash( 'blog_id', $blog->id );
$ctx->__stash[ 'vars' ][ 'foo' ] = 'bar';
$tmpl = <<< EOM
<pre>
<mt:var name="foo">
<mt:BlogURL setvar="blog_url">
<MTBlogName>
<MTEntries include_blogs="children">
<MTEntryTitle>
</MTEntries>
EOM;
require_once( 'MTUtil.php' );
require_once( 'modifier.mteval.php' );
$contents = smarty_modifier_mteval( $tmpl, TRUE );
echo $contents;
echo $ctx->__stash[ 'vars' ][ 'blog_url' ];
?>
動的にテンプレートタグを追加する
add_tag
タグ名と、関数名を渡して、ファンクションタグを登録します。以下の例では、mt:Bar タグで、Barを出力します。
$ctx->add_tag( 'bar', 'bar' );
function bar( $args, &$ctx ) {
return 'Bar';
}
// <mt:bar> => Bar
add_container_tag
タグ名と、関数名を渡して、ブロックタグを登録します。以下の例では、<mt:buz>〜</mt: buz>で、1から5までの数字を<mt:var name="__counter__">タグで出力します。
$ctx->add_container_tag( 'buz', 'buz' );
function buz( $args, $content, &$ctx, &$repeat ) {
$localvars = array( '__counter__' );
if ( isset( $args[ 'max' ] ) ) {
$max = $args[ 'max' ];
} else {
$max = 5;
}
if (! isset( $content ) ) {
$ctx->localize( $localvars );
$ctx->__stash[ 'vars' ][ '__counter__' ] = 0;
}
$counter = $ctx->__stash[ 'vars' ][ '__counter__' ];
if ( $counter < $max ) {
$repeat = TRUE;
$counter++;
$ctx->__stash[ 'vars' ][ '__counter__' ] = $counter;
$ctx->stash( 'counter', $counter );
} else {
$ctx->restore( $localvars );
$repeat = FALSE;
}
return $content;
}
ブロックタグの作り方は、ファンクションタグと違って少し複雑ですが、以下のように理解してください。
- 引数は、$args, $content, &$ctx, &$repeat
- $argsには、タグに渡されるモディファイアがキーバリューの配列で格納されている
- $repeat が TRUEの間、繰り返し呼び出される
- ループの1回目は、isset( $content ) はFALSEである(なので、これで分岐して初期化等を行う)
- $ctx->localize( $localvars ); でテンプレート変数の初期化
- $ctx->restore( $localvars ); で、初期化したテンプレート変数をリストア(戻す)
5、6ですが、ループの中でループを使っている時なんかで、__counter__の値が親ループの中の値なのか、子ループの中の値なのかが同じ変数名なのでわかんなくなりますよね。変数のスコープを局所化するという理解で良いと思います。
__stash は、クラスのプロパティ、stashはクラスのメソッドです。ややこしい? けど、要はキャッシュです。値をセットするのに使われます。stashメソッドでは第一引数にキャッシュのキー、第二引数にキャッシュの値(オブジェクトや配列、もしくはスカラ何でも)を指定します。第二引数を省略すると、キャッシュされた値を取得します。
$ctx->stash( 'blog', $blog );
__stashはプロパティで、配列(のキーが) varsに指定した値が、mt:var name='"hoge"で取得できます。
$ctx->__stash[ 'vars' ][ '__counter__' ] = $counter;
add_conditional_tag
タグ名と、関数名を渡して、条件タグ(mt:ifなんとか)を登録します。以下の例では、常に真を返す mt:ifqux条件タグを登録しています(常に真、って意味がないんですけど、サンプルとして)。
$ctx->add_conditional_tag( 'ifqux', 'ifqux' );
function ifqux( $args, $content, &$ctx, &$repeat ) {
return $ctx->_hdlr_if( $args, $content, $ctx, $repeat, TRUE );
}
返り値 $ctx->_hdlr_if( $args, $content, $ctx, $repeat, TRUE ); のように、第5引数に真偽を指定します。
add_global_filter
モディファイア名と、関数名を渡して、グローバルモディファイアを登録します。以下の例ではモディファイアに渡した文字列を連結して出力するcorgeモディファイアを登録しています。
$ctx->add_global_filter( 'corge', 'corge' );
function corge( $text, $arg ) {
return $text . $arg;
}
// <mt:bar corge="!!"> => Bar!!
ちょっと長くなりますが、ソースは下記のようになります。
<?php
$blog_id = 1;
include('/path/to/mt/php/mt.php');
$mt = MT::get_instance( $blog_id, '/path/to/mt/mt-config.cgi' );
$ctx =& $mt->context();
$ctx->caching = FALSE;
$blog = $mt->db()->fetch_blog( $blog_id );
$ctx->stash( 'blog', $blog );
$ctx->stash( 'blog_id', $blog->id );
$ctx->add_tag( 'bar', 'bar' );
$ctx->add_container_tag( 'buz', 'buz' );
$ctx->add_conditional_tag( 'ifqux', 'ifqux' );
$ctx->add_global_filter( 'corge', 'corge' );
$tmpl = <<< EOM
<pre>
<mt:bar corge="!!">
<mt:buz>
<mt:var name="__counter__">
</mt:buz>
<mt:ifqux>
It is true.
<mt:else>
It is false.
</mt:ifqux>
EOM;
require_once( 'MTUtil.php' );
require_once( 'modifier.mteval.php' );
$contents = smarty_modifier_mteval( $tmpl, TRUE );
echo $contents;
function bar( $args, &$ctx ) {
return 'Bar';
}
function buz( $args, $content, &$ctx, &$repeat ) {
$localvars = array( '__counter__' );
if ( isset( $args[ 'max' ] ) ) {
$max = $args[ 'max' ];
} else {
$max = 5;
}
if (! isset( $content ) ) {
$ctx->localize( $localvars );
$ctx->__stash[ 'vars' ][ '__counter__' ] = 0;
}
$counter = $ctx->__stash[ 'vars' ][ '__counter__' ];
if ( $counter < $max ) {
$repeat = TRUE;
$counter++;
$ctx->__stash[ 'vars' ][ '__counter__' ] = $counter;
$ctx->stash( 'counter', $counter );
} else {
$ctx->restore( $localvars );
$repeat = FALSE;
}
return $content;
}
function ifqux( $args, $content, &$ctx, &$repeat ) {
return $ctx->_hdlr_if( $args, $content, $ctx, $repeat, TRUE );
}
function corge( $text, $arg ) {
return $text . $arg;
}
?>
出力結果は、以下のようになります。
Bar!!
1
2
3
4
5
It is true.
他に、add_token_tag というのがあるのですが(mt:subcategoriesのように再帰的に呼ばれるタグ)、使うケースは少ないように思いますので、今回は省略しました。
では、また。