php twig - 将函数传递给模板

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3595727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 10:21:18  来源:igfitidea点击:

twig - pass function into template

phpfunctioninheritancetwigtemplate-engine

提问by StoneHeart

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?

是否可以?

回答by Austin Hyde

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()你的这个函数是为了修改一个现有的变量,那么它就是一个filter

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. This means they are isolated in terms of their environment, and can only represent the contextyou pass them via the data array you pass in the $template->render()method.

需要记住的是,在 MVC 方面,Twig 模板代表一个视图。这意味着它们就其环境而言是隔离的,并且只能表示您通过在方法中传递的数据数组传递给它们的上下文$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 badthing.

这是一件好事,因为它使您的演示文稿与您的逻辑和数据分离。如果你可以随意调用函数,那么你会突然增加这种耦合,这是一件坏事

The other reason for this is the way PHP handles callbacks. Think about how you would have to pass that function into your template... Probably something like this:

另一个原因是 PHP 处理回调的方式。想想你将如何将该函数传递到你的模板中......可能是这样的:

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 blahis 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. You are notpassing the function, just it's name.

在普通 PHP 中,当您使用这样的变量函数时(尝试像函数一样使用字符串变量),它(或多或少)会执行该函数的查找,然后调用它。你没有传递函数,只是它的名字。

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.

如果你想要更多的文档,官方文档在这里

回答by Corrensanders

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.

我和你一样迷茫,我的朋友,但在网上搜索答案并没有找到答案后,我决定看看我是否可以自己做。因此,我想在这里发布我的解决方案(即使我知道这篇文章很旧),因为如果您搜索此问题,这是 google 上的第一次点击。

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()".

所以现在我们有 $values 作为一个数组,它包含这个带有函数“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 }}

回答by Plamen Dragiyski

Although you cannot PHP callable directly, twig is extensible. You can add a callable filter, so you can apply to PHP functions passed to template.

尽管您不能直接调用 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);
    }

}

Now if you pass variable my_functo template, you can do 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.

现在,如果将变量传递my_func给模板,则可以执行my_func|call(arg1, arg2). 你甚至可以做高阶函数"array_filter"|call(my_array, my_func),你总是可以在过滤器中做更多的事情,比如接受数组作为参数等等。

回答by merqlove

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

回答by Ajsti.pl - Maciej Szewczyk

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