我正在尝试是否使用变量来调用特定的宏名称。
我有一个正在导入的宏文件
{% import 'form-elements.html.twig' as forms %}
现在该文件中有所有表单元素宏:文本、文本区域、选择、单选等。
我有一个传入的数组变量,其中包含一个元素:
$elements = array(
array(
'type'=>'text,
'value'=>'some value',
'atts'=>null,
),
array(
'type'=>'text,
'value'=>'some other value',
'atts'=>null,
),
);
{{ elements }}
我想做的是从宏生成这些元素。当被叫名字时,它们工作得很好:
{{ forms.text(element.0.name,element.0.value,element.0.atts) }}
但是我想做的是这样的:
{% for element in elements %}
{{ forms[element.type](element.name,element.value,element.atts) }}
{% endfor %}
我尝试了以下所有方法,但都导致了相同的错误:
{{ forms["'"..element.type.."'"](element.name,element.value,element.atts) }}
{{ forms.(element.type)(element.name,element.value,element.atts) }}
{{ forms.{element.type}(element.name,element.value,element.atts) }}
不幸的是,这会引发以下错误:
Fatal error: Uncaught exception 'LogicException' with message 'Attribute "value" does not exist for Node "Twig_Node_Expression_GetAttr".' in Twig\Environment.php on line 541
任何有关解决方案或更好的模式的帮助或建议都会非常有帮助。
我只是认为其他人可能想要这个问题的答案,由 fabpot 提供:
这确实是不支持的:使用动态名称调用宏(我添加了一个适当的异常以更清楚地了解该问题)。
如果您确实想这样做,可以使用以下代码来实现:
{{ 属性(forms, element.type, [element.name,element.value,element.atts]) }}
-fabpot
https://github.com/twigphp/Twig/issues/922#issuecomment-11133299
Twig 可能不支持动态宏。
但是有一个简单的解决方法,因为您可以动态包含其他模板。
示例:
假设您的网站有一堆内容模块或内容块(或者您想如何称呼它们)。并且您有 Twig 宏负责渲染每个模块。
{# modules.twig #}
{% macro module1(config) %}
<div>module one</div>
{% endmacro %}
{% macro module2(config) %}
<div>module two</div>
{% endmacro %}
{% macro module3(config) %}
<div>module three</div>
{% endmacro %}
现在,动态调用这些宏需要为每个宏添加一个额外的模板,如下所示:
{# module1.twig #}
{% import "modules.twig" as modules %}
{{ modules.module1(config) }}
{# module2.twig #}
{% import "modules.twig" as modules %}
{{ modules.module2(config) }}
{# module3.twig #}
{% import "modules.twig" as modules %}
{{ modules.module3(config) }}
最后,在实际的页面模板中,您只需包含模板而不是调用宏。
{# template.twig #}
{# this is the macro's name to be called #}
{% set macro = 'module2' %}
{# this is just a config object to be passed to the macro #}
{% set config = {} %}
{% include macro ~ '.twig' with { config: config } only %}
Et voilá,(动态生成的)输出将是
<div>module two</div>
。
如果您的环境中启用了 Twig
template_from_string()
功能,您可以通过以下方式完成此操作:
{% set macroName = 'bing' %}
{% set tmplString = "{% import 'macros.twig' as macros %}{{ macros.#{macroName}( arg1, arg2 ) }}"
{{ include(
template_from_string(tmplString),
{ arg1: 'bong', arg2: 'bang' }
) }}
基本上与@Arvid的答案相同,但允许您在字符串中创建模板并动态包含它,而不必创建单独的文件。
https://twig.symfony.com/doc/3.x/functions/template_from_string.html