PHP におけるクロージャの用途

PHPでクロージャ
作ってみたものの、実はあんまり用途が思い浮かんでない。
なんとなく、 array_walk がキーワードに浮かんでは来るけど。


てことで、とりあえず smarty で使ってみようと思う。


CakePHP ã‚’完全 smarty 化してみたものの、
smarty 内での配列の扱いが微妙だ。

↓事の顛末はこの辺に。
http://d.hatena.ne.jp/am11op/20070614/1181837256

要は、php ならこう書くべきところを

<?php echo $html->link('Edit', array('action'=>'edit', 2));?>

smarty では view に変なメソッド作った上でこう書く必要があった。

{$html->link('Edit', $view->_array('action=>edit', 2))}

まあ、これでもよいんだけど、せっかくなんで closure (的なもの)を使ってみる。

Closure はこんなの。

class Closure {
    var $_args;
    var $_func;
    /**
     * @private
     */
    function Closure($func=null, $args=null) {
        if ($func) {
            $this->_args = $args;
            $func = ereg_replace("^function\([^\)]*\) *\{", "", $func);
            $func = ereg_replace("\}$", "", $func);
            $this->_func = $func;
        }
    }
    
    /**
     * @param $func string closure
     * @param $arg1 $mixed first object/var which is used in $func
     * @param $arg2 $mixed second object/var which is used in $func
     * ...
     */
    function bind() {
        $args = func_get_args();
        return new Closure(array_shift($args), $args);
    }

    /**
     * use this method to call closure 
     */    
    function call() {
        $func = create_function('$args', $this->_func);
        return $func($this->_args);
    }
    
    function func() {
        $args = func_get_args();
        $obj = new Closure(array_shift($args), $args);
    	return $obj->call();
    }
}


無駄にインスタンス量産してるのは、書き直すのが面倒だったから。
このクラスを closure という名前で assign_by_ref してやって、
smarty 内からこう使う。

{*$html->link('Edit', $view->_array('action=>edit', 2))*}
{$html->link('Edit', $closure->func("return array('action'=>'edit', 2);"))}

文字数増えてる!
ネタです!

まあ、ちょっと変数を php で処理して何かのメソッドに渡したい時、
一回しか使わないような modifier をいちいち作らなくてよいので便利かも。
ただし、入力値に対して使う場合は任意のコードを実行されないように気をつけること(棒読み)。