是否有可能在扩展中获得小枝变量值?


Is it possible to get a twig variable value in an extension

我正在使用Symfony2组件对遗留应用程序进行现代化改造。我一直在尝试(和大多数失败)替换旧的php模板与小枝。

我纠结的部分是:每个子模板都有自己的类,包含自己的逻辑(告诉过你这都是关于遗留的)。

因此,我创建了一个分支扩展,它调用模板类,然后包括子模板,将类定义的变量传递给它(这是扩展代码)。

例句:

{% template "NavBlockTemplate" %}

  • 创建新的NavBlockTemplate实例。
    • 调用getTemplateName获取包含
    • 的小枝模板文件
    • 调用getVariables获取模板
    • 所需的变量
    • 用给定的变量
    • 创建上述模板的Twig_Node_Include

遗憾的是:每个模板都可以将变量传递给它的子模板类构造函数…

所以,我需要的,但不确定它是否可能,是这样的:

{% template "NavBlockTemplate" with { 'varName': value, 'var_id': otherVar.id } 
  • 编译从Twig_Expression对象到php的变量
  • 用php编译vars创建一个新的NavBlockTemplate实例
    • 调用getTemplateName获取包含
    • 的小枝模板文件
    • 调用getVariables来获取模板
    • 所需的变量
    • 用给定的变量
    • 创建模板的Twig_Node_Include

那么,这可能吗?有什么建议吗?

在模板编译过程中不能访问变量值。目前还没有。当你调用render($name, $context)时,Twig有两个不同的阶段:

  • 首先编译模板(如果缓存中还没有可用)
  • 第二次渲染。

通过Twig_Environment::render()的实现可以很容易地看到这两个步骤:

public function render($name, array $context = array())
{
    return $this->loadTemplate($name)->render($context);
}

您的自定义标签需要考虑到这一点。它需要创建一个特殊的节点类,它将被编译成您需要的逻辑。你可以看看现有的Twig标签的实现方式。
甚至您所包含的类名也可以在编译时访问。$expr->getAttribute('value')只在表达式是常量表达式的情况下才会起作用,并且您没有在解析器中强制执行它。

另一方面,在这种情况下使用标记可能不是最好的解决方案(虽然它是最复杂的解决方案)。根据Twig的语义,一个函数会更好。这正是Twig引入include()函数的原因,因为它更适合。这就是它的样子。

:

{{ include_legacy("NavBlockTemplate", { 'varName': value, 'var_id': otherVar.id }) }}

扩展名:

class LegacyIncludeExtension extends 'TwigExtension
{
    public function getFunctions()
    {
        return array(
            new 'Twig_SimpleFunction(
                'include_legacy',
                array($this, 'includeLegacy'),
                array('is_safe' => array('all'), 'needs_environment' => true, 'needs_context' => true)
            ),
        );
    }
    public function includeLegacy('Twig_Environment $env, array $context, $name, array $variables = array())
    {
        $fqcn = // determine the class name
        $instance = new fqcn();
        $template = $instance->getTemplateName();
        $variables = array_merge($instance->getVariables(), $variables);
        return $env->resolveTemplate($template)->render(array_merge($context, $variables));
    }
}

方法的最后一行执行twig_include的主要工作。如果您需要隔离上下文的支持,这很容易(使模板的数组合并有条件)。支持ignore_missing需要更多的工作,在这种情况下,您最好直接调用twig_include:

    public function includeLegacy('Twig_Environment $env, array $context, $name, array $variables = array(), $withContext = true, $ignoreMissing = false)
    {
        $fqcn = // determine the class name
        $instance = new fqcn();
        $template = $instance->getTemplateName();
        $variables = array_merge($instance->getVariables(), $variables)
        return twig_include($env, $context, $template, $variables, $withContext, $ignoreMissing);
    }