将代码添加到编译模板的构造函数中

时间:2014-09-30 05:04:26

标签: symfony twig

所以我有这个Twig扩展,它允许添加命名小部件,这些小部件可以从数据库中获取内容并回显它们,或回显标签内的回退内容:

{% widget 'my_text' %}
Hello world
{% endwidget %}

我已经设置了一个Twig扩展来执行此操作。它由一个节点访问者组成,它在没有缓存时收集我的节点,并将他们的密钥添加到一个数组中,然后用于进行数据库调用:

class WidgetNodeVisitor implements \Twig_NodeVisitorInterface
{

    private $aliases = array();

    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ($node instanceof WidgetNode) {
            $env->getExtension('widget')->addAlias($node->getNode('alias')->getAttribute('value'));
        }

        return $node;
    }
    /...

令牌解析器相当基本,大部分类似于{% trans %}{% endtrans %}解析器,因此不需要提供其代码(并且它运行良好)。

节点类本身如下所示:

class WidgetNode extends \Twig_Node
{
    public function __construct(\Twig_NodeInterface $alias, \Twig_NodeInterface $body, $lineno = 0, $tag = null)
    {
        parent::__construct(array('alias' => $alias, 'body' => $body), array(), $lineno, $tag);
    }

    public function getName()
    {
        return $this->attributes['name'];
    }

    public function compile(\Twig_Compiler $compiler)
    {
        $compiler->addDebugInfo($this);

        $alias = $this->nodes['alias']->attributes['value'];
        $fallback = \addslashes($this->nodes['body']->attributes['data']);

        // This method fetches the data from the DB or cache
        $compiler->raw("echo \$this->env->getExtension('widget')->getWidget('$alias', '$fallback');\n");
    }
}

我的问题是,每个编译后的WidgetNode都会在getWidget()中生成一个数据库调用。如果我的模板中有很多这样的节点,那么数据库负载会太高。所以,我认为我可以收集整个模板所需的小部件别名,然后让我的扩展程序使用alias IN (...) SQL查询获取所有需要的小部件,但为此,我需要一种方法以某种方式修改缓存的模板__constructdoDisplay方法,以便调用我的扩展程序来获取所需的所有小部件:

class __TwigTemplate_6f3bb8f1b5ab540431a1ab3ff48c625b58765e4f0d0d284fe05a9353ea714de8 extends Twig_Template
{
    public function __construct(Twig_Environment $env)
    {
        parent::__construct($env);

        // We've visited the nodes prior to compilation, so the actual string aliases should be known
        $env->getExtension('widget')->prefetch(array('widget1', 'widget2', ...));
    }

但是如何让Twig修改基本模板模板?我尝试用一​​个包装器交换任何\Twig_Node_Module,这个包装器会以不同的方式呈现缓存的模板构造函数,但似乎我的更改不起作用。我尝试在NodeVisitor进行交换。

此外,我已经注意到'traits'节点可能会影响Twig对模板缓存的渲染,尽管没有文档或任何内容。

有关如何在扩展程序中修改缓存模板标题的任何建议吗?

UPD。作为Christophe Coevoet的suggested,包裹\Twig_Node_Module是正确的方法:

  

但是,通过将Twig_Node_Module包装在节点中的自己的节点中   访问者,你可以在doDisplay中添加一些逻辑   覆盖compileDisplayHeader或compileDisplayBody。

Cristophe还建议将Kris Wallsmith's blog post on Twig node visitors作为此类修复的起点。

0 个答案:

没有答案