简体   繁体   English

如何在 twig 2 中获取 _self 的对象 - 使用字符串,属性(_self,函数)在更新后总是失败

[英]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_macrotwig

        {% 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM