[英]How can I get an object of _self in twig 2- With a string the attribute( _self, function) fails always after update
I will update our twig to 2.11.我会将我们的树枝更新到 2.11。 We use folowing code currently:
我们目前使用以下代码:
{% set neededFunction = 'someting_dynamic' %}
{% import _self as functions %}
{% if attribute(functions, neededFunction ) is defined %}
{# do something #}
{% else %}
{# do something else #}
{% endif %}
but after update "attribute(functions, neededFunction )" fails always.但更新后“属性(功能,需要的功能)”总是失败。 I think its because _self is no object now.
我认为这是因为 _self 现在不是对象。 But what can i do now to check if a dynamic named function exist?
但是我现在可以做什么来检查动态命名函数是否存在?
update:更新:
I tried the following:我尝试了以下方法:
{% set neededFunction = 'someting_dynamic' %}
{% import 'myTemplate' as functions %}
{% if attribute(functions, neededFunction ) is defined %}
{# do something #}
{% endif %}
{% if functions.neededFunction is defined %}
{# do something #}
{% endif %}
{% if functions.someting_dynamic is defined %}
{# do something #}
{% endif %}
only the last one works.只有最后一个有效。 But this is not dynamic
但这不是动态的
update: Try to solve the Problem with the approach of DarkBee.更新:尝试用DarkBee的方法解决问题。
Now there is one last Problem:现在还有最后一个问题:
Before I compile a Macro, I want to check, if the Macro exist.在编译宏之前,我想检查宏是否存在。 If not, I want to call a default macro.
如果没有,我想调用一个默认宏。 But I have the problem, that the $function is not compiled.
但是我有一个问题,就是 $function 没有被编译。 Can i get the Value of the compiled content from parser?
我可以从解析器获取编译内容的值吗?
My TokenParser:我的令牌解析器:
class DynamicMacro extends \Twig\TokenParser\AbstractTokenParser
{
const MAX_MACROS = 2;
/**
* @var Node
*/
private $firstAvailableNode;
/**
* {@inheritDoc}
*/
public function getTag()
{
return 'dynamic_macro';
}
/**
* {@inheritDoc}
*/
public function parse(Token $token)
{
$stream = $this->parser->getStream();
$name = $stream->expect(Token::NAME_TYPE)->getValue();
for ($i = 1; $i <= self::MAX_MACROS; $i++) {
if (!$stream->test(Token::BLOCK_END_TYPE)) {
$this->checkMacro( $token, $name );
}
}
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
return $this->getFirstAvailableNode();
}
private function checkMacro( Token $token, string $name )
{
$stream = $this->parser->getStream();
$stream->expect(\Twig_Token::PUNCTUATION_TYPE);
$function = $stream->expect(\Twig_Token::NAME_TYPE)->getValue();
$arguments = $this->parser->getExpressionParser()->parseArguments(true);
/** @todo: $function -> 'fx' has to be compiled */
if (is_null($this->firstAvailableNode) && $this->parser->hasMacro($function)){
$node = new DynamicMacroNode($name, $function, $arguments, $token->getLine(), $this->getTag());
$this->setFirstAvailableNode($node);
}
}
/**
* @return Node
*/
public function getFirstAvailableNode(): Node
{
if(is_null($this->firstAvailableNode))
return new EmptyNode();
return $this->firstAvailableNode;
}
/**
* @param Node $node
*/
public function setFirstAvailableNode(Node $node)
{
if (is_null($this->firstAvailableNode))
$this->firstAvailableNode = $node;
}
}
Twig Snipped:树枝剪断:
{% import _self as foo_macro %}
{% set fx = 'foo_function' %}
{% set fxdef = 'foo_function_default' %}
{% dynamic_macro foo_macro.fx('bar', 'foo', 42, fx).fxdef('bar', 'foo', 42, fx) %}
{% macro foo_function_default(bar, foo, int, function) %}
Bar: {{ bar }}<br />
Foo: {{ foo }}<br />
Int: {{ int }}<br />
Fx: {{ function }}<br />
{% endmacro %}
You could create your own tag in twig
which solves this isue你可以在创建自己的标签
twig
解决了这个isue
Register custom TokenParser
inside your extension:在您的扩展中注册自定义
TokenParser
:
class MyTwigExtension implements \Twig\Extension\ExtensionInterface {
public function getTokenParsers() {
return [
new DynamicMacro(),
];
}
}
Create the TokenParser
创建
TokenParser
class DynamicMacro extends \Twig\TokenParser\AbstractTokenParser {
/**
* {@inheritDoc}
*/
public function getTag()
{
return 'dynamic_macro';
}
/**
* {@inheritDoc}
*/
public function parse(\Twig\Token $token)
{
$parser = $this->parser;
$stream = $parser->getStream();
$name = $stream->expect(\Twig_Token::NAME_TYPE)->getValue();
$stream->expect(\Twig_Token::PUNCTUATION_TYPE);
$function = $stream->expect(\Twig_Token::NAME_TYPE)->getValue();
$arguments = $this->parser->getExpressionParser()->parseArguments(true);
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return new DynamicMacroNode($name, $function, $arguments, $token->getLine(), $this->getTag());
}
}
Create the Node
创建
Node
class DynamicMacroNode extends \Twig\Node\Node {
public function __construct($name, $function, $arguments, $lineno, $tag = null) {
$attributes = [
'name' => $name,
'function' => $function,
'lineno' => $lineno,
];
parent::__construct([ 'arguments' => $arguments, ], $attributes, $lineno, $tag);
}
public function compile(\Twig_Compiler $compiler) {
$compiler->write('$_dynamicMacro_parms = [];')
->raw("\n");
foreach($this->getNode('arguments') as $argument) {
$compiler->write('$_dynamicMacro_parms[] = ')
->subcompile($argument)
->raw(";\n");
}
$compiler->write('echo twig_call_macro($macros[\''.$this->getAttribute('name').'\'], \'macro_\'.$context[\''.$this->getAttribute('function').'\'] ?? null, $_dynamicMacro_parms,'.$this->getAttribute('lineno').', $context, $this->getSourceContext());');
}
}
Now you can use the tag dynamic_macro
inside twig
现在,您可以使用标签
dynamic_macro
内twig
{% import _self as foo_macro %}
{% set fx = 'foo_function' %}
{% dynamic_macro foo_macro.fx('bar', 'foo', 42, fx) %}
{% macro foo_function(bar, foo, int, function) %}
Bar: {{ bar }}<br />
Foo: {{ foo }}<br />
Int: {{ int }}<br />
Fx: {{ function }}<br />
{% endmacro %}
please not this only a rough version on how you can solve this issue and should be further expanded with validating the data and such请不要这只是一个关于如何解决这个问题的粗略版本,应该通过验证数据等进一步扩展
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.