【问题标题】:Twig: Selecting certain blocks and rendering themTwig:选择某些块并渲染它们
【发布时间】:2011-11-26 13:41:30
【问题描述】:

我正在将 Twig 模板引擎集成到 PHP 应用程序中。特别是,我想使用 twig 引擎来渲染表单。

看过 symfony2 如何使用 twig 渲染表单小部件,他们有一个巨大的模板文件,其中包含所有小部件,如下所示:

(...)
{% block password_widget %}
{% spaceless %}
    {% set type = type|default('password') %}
    {{ block('field_widget') }}
{% endspaceless %}
{% endblock password_widget %}

{% block hidden_widget %}
    {% set type = type|default('hidden') %}
    {{ block('field_widget') }}
{% endblock hidden_widget %}

{% block email_widget %}
{% spaceless %}
    {% set type = type|default('email') %}
    {{ block('field_widget') }}
{% endspaceless %}
{% endblock email_widget %}

{% block test_widget %}
{% spaceless %}
   <div>
     {{test}}
   <div>
{% endspaceless %}
{% endblock test_widget %}

(...)

我的问题是如何从这个模板中“抓取”块并渲染它们?

到目前为止,我能够加载模板,并调用 get blocks 来获取所有块:

twig = new \Twig_Environment($loader, array('cache' => 'cache'));
$template = $twig->loadTemplate('view\form_div_layout.html.twig');
//var_dump($template->getBlocks()); //try getting all blocks
$template->displayBlock('test_widget', array('test' => 'test'));
echo $template->render();

不幸的是,在这种情况下,我无法仅渲染“test_widget”块。我应该怎么做才能从模板中检索“test_widget”块,然后将其插入到不同的模板中以呈现整个表单?

【问题讨论】:

  • 这可能对我有用,您能否分享一下您是如何实例化或使用$loader 的?

标签: php symfony twig


【解决方案1】:

原来应该使用$template-&gt;renderBlock('blockname', array('test' =&gt; 'test'));。这将使 twig 渲染该块,然后返回一个包含该块标记的字符串。然后可以使用 echo 显示它或将其插入到其他模板中。

完整示例:

$loader = new \Twig_Loader_Filesystem(array('/my-template-root'));
$twig = new \Twig_Environment($loader, array('debug' => true));
$template = $twig->loadTemplate('view\form_div_layout.html.twig');
$result = $template->renderBlock('blockname', array('test' => 'test'));
echo $result;

【讨论】:

  • 第二个参数有什么用?
  • 第二个参数是模板中出现的变量数组。例如,{{ test }}
  • 我很难弄清楚这部分,因为当我这样做时,我遇到了一个异常,好像也需要一个 USE 状态。你是说如果需要扩展树枝引擎,这已经扩展/嵌入了 no USE 语句?即使我这样做了,它也不起作用。
  • @BrianThomas 您收到的异常消息是什么?
  • 使用 load() 代替,它不是 @internal 不像 loadTemplate()
【解决方案2】:

如果您使用 Symfony 并且希望仍然能够访问全局变量(appapp.user 等),那么这非常有用:

private function renderBlock($template, $block, $params = [])
{
    /** @var \Twig\Environment $twig */
    $twig = $this->get('twig');
    /** @var \Twig\TemplateWrapper $template */
    $template = $twig->load($template);

    return $template->renderBlock($block, $twig->mergeGlobals($params));
}

我刚刚添加了这在我的控制器上有一个私有功能。效果很好。感谢@F21 为我指明了正确的方向。

【讨论】:

  • 改用load(),它不是@internal,不像loadTemplate()
【解决方案3】:

这太棒了!我还想补充一点,有一个hasBlock 函数允许您在尝试进行模板渲染之前进行验证。这使您可以验证模板是否按预期构建,或者在我的情况下具有可选块。对于它的价值,这是我的一个控制台应用程序中的一个示例,它发送通知电子邮件

        $templateContent = $this->getContainer()->get('twig')->loadTemplate('FTWGuildBundle:AuctionNotification:notificationEmail.html.twig');
        $body = $templateContent->renderBlock('body', array('siteDomain' => $siteClient->getSiteDomain(), 'staticContentDomain' => $siteClient->getStaticContentDomain(), 'batch' => $batch->getNotifications(), 'auction_notification_lockout_period' => $this->getContainer()->getParameter('auction_notification_lockout_period')));
        $subject = ($templateContent->hasBlock("subject")
            ? $templateContent->renderBlock("subject", array('batchSize' => $batch->getSize(), 'batch' => $batch))
            : "Auction House Notifications");

【讨论】:

    【解决方案4】:

    注意:如果模板扩展或嵌入父块,hasBlock 将不起作用。

    https://github.com/twigphp/Twig/issues/450

    【讨论】:

      猜你喜欢
      • 2020-01-18
      • 1970-01-01
      • 2022-11-08
      • 1970-01-01
      • 2020-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-20
      相关资源
      最近更新 更多