23

目前我将我的函数放在一个类中,并将这个类的一个实例传递给模板,并将我需要的函数作为类方法调用。

{{ unneededclass.blah() }}

我需要像下面那样做

{{ blah() }}

是否可以?

4

5 回答 5

33

2015 年 5 月 14 日更新

评论者指出,我大多是错的。如果您真的需要一个函数,而不是过滤器或宏,您可以按照Twig 文档中的建议进行操作:

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

(第一个参数是您要过滤的变量,第二个是通过正常方式提供的)

如果,如您在上面指出的,您的函数只是输出 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()

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

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

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

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

在您的模板中,上下文变量blah现在只是一个包含'blah'.

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

问题是,您不可能将函数传递给模板,因为 PHP 执行此操作的唯一机制是通过名称字符串,并且一旦进入模板,该名称就不再是函数名称而只是字符串。

有点啰嗦,但我希望这有帮助!

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

于 2010-08-29T18:06:55.783 回答
7

虽然您不能直接调用 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),你总是可以在过滤器中做更多的事情,比如接受数组作为参数等等。

于 2014-03-25T15:03:59.150 回答
6

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

到这里,其实很简单:

我创建了一个包含我的函数和变量的类,例如:

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

所以现在我们将 $values 作为一个数组,其中包含这个对象和一个函数“getRandomNumber()”。

渲染模板文件时,将此类作为值包含:

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

这样,在模板文件中,您只需调用此方法即可调用函数并获取结果:

{{ functions.getRandomNumber }}
于 2012-08-15T14:12:41.210 回答
2

完整答案: 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') }}
于 2013-09-30T14:08:40.663 回答
1

使用匿名类

在管理器/控制器/服务中创建匿名类..

     $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) %}
于 2018-05-16T07:12:31.477 回答