是否有可能在扩展中获得一个树枝变量值
Is it possible to get a twig variable value in an extension
我正在使用 Symfony2 组件对遗留应用程序进行现代化改造。
我一直在尝试(但大部分都失败了)用 twig 模板替换旧的 php 模板。
我正在努力解决的部分是:每个子模板都有自己的 class 包含自己的逻辑(告诉过你这都是关于遗留的)。
因此,我创建了一个调用模板 class 的 twig 扩展,然后包含子模板,将 class 定义的变量 (Here's the extension code) 传递给它。
例如:
{% template "NavBlockTemplate" %}
- 创建一个新的
NavBlockTemplate
实例。
- 调用
getTemplateName
获取要包含的 twig 模板文件
- 调用
getVariables
获取模板所需的变量
- 使用给定的变量
创建所述模板的Twig_Node_Include
这里可悲的部分是:每个模板都可以将变量传递给它的子模板 class 构造函数 ...
所以,我需要但不确定它是否可能是这样的:
{% template "NavBlockTemplate" with { 'varName': value, 'var_id': otherVar.id }
- 使用从
Twig_Expression
个对象到 php 个变量的变量进行编译
- 创建一个新的
NavBlockTemplate
实例 php 编译变量
- 调用
getTemplateName
获取要包含的 twig 模板文件
- 调用
getVariables
获取模板所需的变量
- 使用给定的变量
创建所述模板的Twig_Node_Include
那么,这可能吗?关于如何实现这一目标的任何提示?
编译模板期间无法访问变量值。它们尚不可用。
当您调用 render($name, $context)
:
时,Twig 有 2 个不同的阶段
- 首先编译模板(如果在缓存中不可用)
- 第二次渲染它。
执行Twig_Environment::render()
:
很容易看出2个步骤
public function render($name, array $context = array())
{
return $this->loadTemplate($name)->render($context);
}
您的自定义标签需要考虑到这一点。它将需要创建一个特殊节点 class,它将被编译成您需要的逻辑。您可以查看现有 Twig 标签的实现方式。
甚至您包含的 class 名称也可以像您一样在编译时访问。 $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);
}
我正在使用 Symfony2 组件对遗留应用程序进行现代化改造。 我一直在尝试(但大部分都失败了)用 twig 模板替换旧的 php 模板。
我正在努力解决的部分是:每个子模板都有自己的 class 包含自己的逻辑(告诉过你这都是关于遗留的)。
因此,我创建了一个调用模板 class 的 twig 扩展,然后包含子模板,将 class 定义的变量 (Here's the extension code) 传递给它。
例如:
{% template "NavBlockTemplate" %}
- 创建一个新的
NavBlockTemplate
实例。- 调用
getTemplateName
获取要包含的 twig 模板文件 - 调用
getVariables
获取模板所需的变量 - 使用给定的变量 创建所述模板的
Twig_Node_Include
- 调用
这里可悲的部分是:每个模板都可以将变量传递给它的子模板 class 构造函数 ...
所以,我需要但不确定它是否可能是这样的:
{% template "NavBlockTemplate" with { 'varName': value, 'var_id': otherVar.id }
- 使用从
Twig_Expression
个对象到 php 个变量的变量进行编译 - 创建一个新的
NavBlockTemplate
实例 php 编译变量- 调用
getTemplateName
获取要包含的 twig 模板文件 - 调用
getVariables
获取模板所需的变量 - 使用给定的变量 创建所述模板的
Twig_Node_Include
- 调用
那么,这可能吗?关于如何实现这一目标的任何提示?
编译模板期间无法访问变量值。它们尚不可用。
当您调用 render($name, $context)
:
- 首先编译模板(如果在缓存中不可用)
- 第二次渲染它。
执行Twig_Environment::render()
:
public function render($name, array $context = array())
{
return $this->loadTemplate($name)->render($context);
}
您的自定义标签需要考虑到这一点。它将需要创建一个特殊节点 class,它将被编译成您需要的逻辑。您可以查看现有 Twig 标签的实现方式。
甚至您包含的 class 名称也可以像您一样在编译时访问。 $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);
}