Smartyでオブジェクトのメソッドチェーンっぽいのを実現する

Smartyってオブジェクトのメソッドチェーンサポートしてないんだね。

-- foo.tpl --

{ $foo->setdata(88)->setdata('a','b')->getdata() }
Fatal error: Smarty error: [in foo.tpl line 2]: syntax error: unrecognized tag: $foo->setdata(88)->setdata('a':'b')->getdata() (Smarty_Compiler.class.php, line 455) in C:\php\includes\Smarty.class.php on line 1092

ということなので仕方なくプラグインでそれっぽいことをできるようなの作ってみた。

-- modifier.chain.php --

<?php

function smarty_modifier_chain($data, $method) {
    if ( func_num_args() > 2 ) {
        $args = func_get_args();
        array_shift($args);
        $method = array_shift($args);
        return call_user_func_array(array(&$data,$method),$args);
    }
    return $data->$method();
}

実際の使い方

-- foo.php --

<?php 

require_once('Smarty.class.php');

class Foo {
    public $data = '';
    
    public function setdata($str1="",$str2="") {
        $this->data .= "[$str1:$str2]";
        return $this;
    }
    
    public function getdata() {
        return $this->data;
    }
}

$s = new Smarty;
$s->template_dir = './templates';
$s->compile_dir = './templates_c';
$s->plugins_dir = './smarty_plugins';
$s->assign('foo',new Foo);
$data = $s->fetch('foo.tpl');
print $data;
-- foo.tpl --

{ $foo|chain:'setdata':88|chain:'setdata':'a':'b'|chain:'getdata' }
$ php foo.php
[88:][a:b]

コードの説明を軽く。

メソッドに渡す引数がなければ単にメソッド呼び出しするだけ。

もし引数がある場合は引数の個数が可変でも対応できるようにfunc_get_args&call_user_func_array関数の組み合わせでメソッド呼び出しする感じ。

chainってのが長いのでmethod chainの略でmcってプラグイン名にするものありかなぁ。まぁいいや。


ちなみに現在絶賛開発中のSmarty3ではオブジェクトのメソッドチェーンは公式に対応された模様

Object method chaining is implemented.
{$object->method1($x)->method2($y)}

http://smarty-php.googlecode.com/svn/branches/Smarty3Alpha/distribution/README

リリースが待ち遠しいぜ。