【问题标题】:twig - pass function into templatetwig - 将函数传递给模板
【发布时间】:2010-08-29 17:10:13
【问题描述】:

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

{{ unneededclass.blah() }}

我需要像下面那样做

{{ blah() }}

有可能吗?

【问题讨论】:

  • 我有一个函数 blah(),我如何传递它并在 twig 中调用它(使用 twig 模板语法?)
  • 这个函数有什么作用?我几周前才开始使用 Twig,但我很确定你不能这样做。如果blah() 修改了现有变量,过滤器是可行的方法。
  • 它打印出一些 html。顺便说一句,谢谢,我会把我的函数放到一个类中。
  • 那么,你见过macros吗? (它们大约在页面的一半处)这可能正是您正在寻找的东西,并且可能比将东西放在类中更容易实现。我将它们用于简单的表单元素和链接。

标签: php function inheritance twig template-engine


【解决方案1】:

2015 年 5 月 14 日更新

评论者指出,我大多是错的。如果你真的需要一个函数,而不是一个过滤器或宏,你可以使用suggested in the Twig docs

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

并使用喜欢

{{ blah() }}

简而言之,不,这是不可能的。

但是,希望并没有消失!

过滤器

如果你的这个函数blah() 是为了修改一个现有的变量,那么它就是一个过滤器

一个例子:

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

为什么?

要记住的是,就 MVC 而言,Twig 模板代表一个视图。这意味着它们在环境方面是孤立的,只能表示您通过$template-&gt;render() 方法中传递的数据数组传递它们的上下文

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

另一个原因是 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 这样做的唯一机制是通过名称字符串,一旦进入模板,该名称就不再是函数名称,而只是一个字符串。

有点啰嗦,但希望对你有帮助!

如果您需要更多文档,官方文档是here

【讨论】:

  • Twig 也支持函数,在某些情况下需要它twig.sensiolabs.org/doc/advanced.html#functions
  • 表单是由函数组成的,伙计
  • “你不可能将函数传递给模板”——你必须在闭包存在之前就写好了。
  • @Mark:天哪,我在想什么?自 2009 年的 5.3 以来一直关闭。我将更新我的答案以反映这一点
  • 这不再是最新的。 Twig_SimpleFunction 已被弃用。现在使用 TwigFunction。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    来吧,其实很简单:

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

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

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

    在渲染模板文件时,将这个类作为一个值包含进来:

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

    这样,在模板文件中,你只需调用这个方法来调用函数并得到你的结果:

    {{ functions.getRandomNumber }}
    

    【讨论】:

      【解决方案4】:

      完整答案: 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') }}
      

      【讨论】:

      • 警告:\Twig_Function_Method 现已弃用,将在 2.x 中删除
      【解决方案5】:

      使用Anonymous class

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

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

      【讨论】:

        猜你喜欢
        • 2012-06-02
        • 2017-12-25
        • 1970-01-01
        • 2012-09-09
        • 2017-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多