简体   繁体   English

twig - 将函数传递给模板

[英]twig - pass function into template

Currently I place my function in a class and pass an instance of this class into template and call my required function as a class method. 目前,我将我的函数放在一个类中,并将此类的实例传递给模板,并将我所需的函数作为类方法调用。

{{ unneededclass.blah() }}

I need to do like below 我需要像下面这样做

{{ blah() }}

Is it possible? 可能吗?

Update 5/14/2015 2015年5月14日更新

Commenters point out that I'm mostly wrong. 评论者指出,我大多错了。 If you really need a function, and not a filter or macro, you can do it as suggested in the Twig docs : 如果您确实需要一个函数,而不是一个过滤器或宏,您可以按照Twig文档中的建议进行操作

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

And use like 并使用像

{{ blah() }}

In short, no, this is not possible. 简而言之,不,这是不可能的。

However, hope is not lost! 但是,希望不会丢失!

Filters 过滤器

If this function blah() of yours is meant to modify an existing variable, then it is a filter . 如果你的这个函数blah()用于修改现有变量,那么它就是一个过滤器

An example: 一个例子:

//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') }}

(The first argument is the variable you are filtering, the second is supplied by normal means) (第一个参数是您要过滤的变量,第二个参数是通过常规方式提供的)

Macros

If, as you have indicated above, your function simply outputs HTML, then it is a good candidate for a macro . 如上所述,如果您的函数只输出HTML,那么它就是宏的一个很好的候选者。

An example: 一个例子:

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

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

Or with parameters: 或者带参数:

{% 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') }}

Why? 为什么?

The thing to remember is that Twig templates represent a view , in terms of MVC. 要记住的是,根据MVC,Twig模板代表一个视图 This means they are isolated in terms of their environment, and can only represent the context you pass them via the data array you pass in the $template->render() method. 这意味着它们在环境方面是孤立的,并且只能通过您在$template->render()方法中传递的数据数组来表示传递它们的上下文

This is a good thing, as it decouples your presentation from your logic and data. 这是一件好事,因为它将您的演示文稿与逻辑和数据分离开来。 If you can arbitrarily call functions, then you suddenly increase that coupling, which is a bad thing. 如果你可以任意调用函数,那么你突然增加了耦合,这是一件坏事

The other reason for this is the way PHP handles callbacks. 另一个原因是PHP处理回调的方式。 Think about how you would have to pass that function into your template... Probably something like this: 考虑一下如何将该功能传递到模板中......可能是这样的:

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

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

In your template, the context variable blah is now just a string containing 'blah' . 在你的模板中,上下文变量 blah现在只是一个包含 'blah'的字符串。

In vanilla PHP, when you use variable functions like this (try to use a string variable like a function), it (more or less) performs a lookup for that function, then calls it. 在vanilla PHP中,当你使用这样的变量函数时(尝试使用像函数一样的字符串变量),它(或多或少)执行查找该函数,然后调用它。 You are not passing the function, just it's name. 没有传递这个功能,只是它的名字。

The thing is, you cannot possibly pass a function into a template, because PHP's only mechanism for doing this is by name-string, and once inside a template, that name is no longer a function name and just a string. 问题是,您不可能将函数传递给模板,因为PHP执行此操作的唯一机制是通过名称字符串,并且一旦进入模板,该名称就不再是函数名称而只是一个字符串。

A little bit long winded, but I hope that helps! 有点长啰嗦,但我希望有所帮助!

If you want more documentation, the official docs are here . 如果您需要更多文档,官方文档就在这里

I was as lost as you were, my friend, but after searching the web for an answer and found none, I decided to see if I could do it myself. 我和你的朋友一样迷茫,但在网上搜索答案后却没有找到答案,我决定看看自己是否能做到。 Therefore, I wanted to post my solution here (even though I know this post is old), because this is the first hit on google if you search for this problem. 因此,我想在这里发布我的解决方案(即使我知道这篇文章是旧的),因为如果你搜索这个问题,这是谷歌的第一次点击。

Here it go, it is quite simple actually: 在这里,它实际上非常简单:

I made a class which contains my functions and variables, for example: 我创建了一个包含我的函数和变量的类,例如:

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

So now we have $values as an array, which contains this object with a function "getRandomNumber()". 所以现在我们将$ value作为一个数组,其中包含带有函数“getRandomNumber()”的对象。

When rendering the template file, include this class as a value: 渲染模板文件时,请将此类包含为值:

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

This way, inside the template file, you can just call this method to call the function and get your result: 这样,在模板文件中,您可以调用此方法来调用函数并获取结果:

{{ functions.getRandomNumber }}

Although you cannot PHP callable directly, twig is extensible. 虽然你不能直接PHP调用,但twig是可扩展的。 You can add a callable filter, so you can apply to PHP functions passed to template. 您可以添加一个可调用的过滤器,这样您就可以应用于传递给模板的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);
    }

}

Now if you pass variable my_func to template, you can do my_func|call(arg1, arg2) . 现在,如果将变量my_func传递给模板,则可以执行my_func|call(arg1, arg2) You can even do higher order functions "array_filter"|call(my_array, my_func) and you can always do more things in filter like accepting array as parameters and so on. 您甚至可以执行更高阶函数"array_filter"|call(my_array, my_func)并且您总是可以在过滤器中执行更多操作,例如接受数组作为参数等等。

Full answer: http://twig.sensiolabs.org/doc/advanced.html#id2 完整答案: http//twig.sensiolabs.org/doc/advanced.html#id2

I prefer to use Twig Extension like this: 我喜欢像这样使用Twig Extension:

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';
    }
}

In template: 在模板中:

{{ sidebar_menu('some text') }}

Using Anonymous class 使用匿名类

Create anonymous class in manager/controller/service .. 在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' => ...]);
    }
};

Paste parameter into view 将参数粘贴到视图中

$params=[
            'functions' => $functions

        ];



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

Use function in view 在视图中使用功能

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM