web-dev-qa-db-ja.com

twig-関数をテンプレートに渡す

現在、関数をクラスに配置し、このクラスのインスタンスをテンプレートに渡して、必要な関数をクラスメソッドとして呼び出しています。

{{ unneededclass.blah() }}

私は以下のようにする必要があります

{{ blah() }}

出来ますか?

23
StoneHeart

2015年5月14日更新

コメント提供者は、私がほとんど間違っていると指摘しています。フィルターやマクロではなく関数が本当に必要な場合は、 Twig docs で推奨)のように実行できます。

_$twig = new Twig_Environment($loader);
$function = new Twig_SimpleFunction('blah', function () {
   // ...
});
$twig->addFunction($function);
_

そして、次のように使用します

_{{ blah() }}
_

要するに、いいえ、これは不可能です。

しかし、希望は失われません!

フィルター

あなたのこの関数blah()が既存の変数を変更することを意図している場合、それはfilterです。

例:

_//in your PHP
function format_date($date_string,$format_string) {
    return date($format_string,strtotime($date_string));
}
$twig_env->addFilter('format_date',new Twig_Filter_Function('format_date'));

{# in your template #}
{{ some_date|format_date('n/j/Y') }}
_

(最初の引数はフィルタリングする変数で、2番目の引数は通常の方法で提供されます)

マクロ

上で示したように、関数が単にHTMLを出力する場合、それはマクロの適切な候補です。

例:

_{# in your template #}
{% macro say_hello() %}
<p>Oh! Hello, world!</p>
{% endmacro %}

{# ... later on ... #}
{{ _self.say_hello() }}
_

またはパラメータ付き:

_{% macro input(name,value,type) %}
<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

{{ _self.input('phone_number','867-5309') }}
{{ _self.input('subscribe','yes','checkbox') }}
_

どうして?

覚えておくべきことは、TwigテンプレートはMVCの観点からビューを表すということです。これは、それらがで分離されていることを意味します。それらの環境の用語であり、$template->render()メソッドで渡すデータ配列を介して渡すcontextのみを表すことができます。

これは、プレゼンテーションをロジックやデータから切り離すので、良いことです。関数を任意に呼び出すことができる場合は、その結合を突然増やします。これは悪いことです。

これの他の理由は、PHPがコールバックを処理する方法です。その関数をテンプレートに渡す方法を考えてください...おそらく次のようなものです:

_function blah() {
    return "<p>Oh! Hello, world!</p>";
}

$template = $twig_env->loadTemplate('template.html');
echo $template->render(array('blah'=>'blah'));
_

テンプレートでは、コンテキスト変数blahは_'blah'_を含む単なる文字列になりました。

バニラPHPでは、このような変数関数を使用すると(関数のように文字列変数を使用しようとします)、(多かれ少なかれ)その関数の検索を実行してから呼び出します。あなたは関数を渡していない、それは名前だけです。

PHPの唯一のメカニズムは名前文字列によるものであり、テンプレート内に入ると、その名前は関数名ではなく単なる文字列であるため、関数をテンプレートに渡すことはできません。

少し長めですが、お役に立てば幸いです。

より多くのドキュメントが必要な場合、公式ドキュメントは ここ です。

33
Austin Hyde

友達、あなたと同じように迷子になりましたが、ウェブで答えを探しても何も見つからなかったので、自分でできるかどうかを確認することにしました。したがって、この問題を検索した場合、これがグーグルでの最初のヒットであるため、私はここに私の解決策を投稿したいと思いました(この投稿は古いことを知っていますが)。

これで、実際には非常に簡単です。

私は自分の関数と変数を含むクラスを作りました、例えば:

class functionContainer{
        function getRandomNumber()
        {
                return Rand();
        }
}
$values = array(
'functions'=> new functionContainer()
);

これで、配列として$ valuesがあり、このオブジェクトには関数「getRandomNumber()」が含まれています。

テンプレートファイルをレンダリングするときは、このクラスを値として含めます。

$twig->render('random.html', $values);

このように、テンプレートファイル内で、このメソッドを呼び出して関数を呼び出し、結果を取得できます。

{{ functions.getRandomNumber }}
6
Corrensanders

PHP直接呼び出すことはできませんが、twigは拡張可能です。呼び出し可能なフィルターを追加できるので、PHP =テンプレートに渡される関数。

_namespace My\Twig\Extension;

class LambdaFilter extends \Twig_Extension {

    public function getName() {
        return 'lambda_filter';
    }

    public function getFilters() {
        return array(
            new \Twig_SimpleFilter('call', array($this, 'doCall'))
        );
    }

    public function doCall() {
        $arguments = func_get_args();
        $callable = array_shift($arguments);
        if(!is_callable($callable)) {
            throw new InvalidArgumentException();
        }
        return call_user_func_array($callable, $arguments);
    }

}
_

これで、変数_my_func_をテンプレートに渡すと、my_func|call(arg1, arg2)を実行できます。高階関数"array_filter"|call(my_array, my_func)を実行することもでき、配列をパラメーターとして受け入れるなど、フィルターで常により多くのことを実行できます。

6

完全な答え: http://twig.sensiolabs.org/doc/advanced.html#id2

私はTwig次のような拡張機能を使用することを好みます:

namespace Some\Twig\Extensions;

class MenuExtensions extends \Twig_Extension
{
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('sidebar_menu', [$this, 'generate_sidebar_menu']),
        );
    }

    public function generate_sidebar_menu($menu){
        return $menu;
    }

    public function getName()
    {
        return 'menu';
    }
}

テンプレート内:

{{ sidebar_menu('some text') }}
2
merqlove

使用 匿名クラス

Manager/controller/serviceに匿名クラスを作成します。

     $functions = new class($router)
    {
        public function __construct($router)
        {
            $this->router = $router;
        }

    public function getRowUrl(FileManager $fileManager)
    {
        if ($fileManager->isNode()) {
            return $this->router->generate('...', ['parent' => ...]);
        }
        return $this->router->generate('...', ['entity' => ...]);
    }
};

パラメータをビューに貼り付けます

$params=[
            'functions' => $functions

        ];



    return new Response($this->twig->render('...:index.html.twig', $params));

ビューで関数を使用

 {% set rowUrl = functions.rowUrl(entity) %}