延迟执行/完成在Twig


Defer execution/completion in Twig

我将Twig与Symfony2框架分开使用,将其分成更小的部分,以更好地满足我(感知到的)需求。我的框架的一部分是一个管理js/css依赖关系的资产管理库,经过预处理,组合,最小化,压缩,输出适当的<link><script>标签,放置在<head><body>的底部。

资产助手只有三个公共函数:require_asset($asset)render_head()render_bottom()。第一个在不同的模板部分中很少使用(我希望将资产的加载保持在应用程序逻辑之外,因此在分支模板中)。其他两个需要在所有资产都被要求之后调用,并且(在资产管理器完成它的工作之后)返回要放置在模板中的适当的和标记。

所有普通模板都扩展基本模板:

base.twig:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>{{ title }}</title>
        <!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
        {{ Assets.headAssets }}
    </head>
    </body>
        {% block body %}
        {% endblock %}
        {{ Assets.bottomAssets }}
    <body>
</html>

这里的{{ Assets.headAssets }}{{ Assets.bottomAssets }}是通过之前声明的Twig全局变量Assets调用前面提到的render_head()render_bottom()方法;

在我的实例中,这个基本模板是从test.twig:

扩展而来的
{% extends "base.twig" %}
{% import "forms.twig" as forms %}
{% block body %}
    {{ Assets.requires('formtest.css') }}
    {{ Assets.requires('testscript.js') }}
    <form method="post">
        {{ forms.form(form) }}
        <input type="submit"/>
    </form>
{% endblock %}

这里,{{ Assets.requires('formtest.css') }}{{ Assets.requires('testscript.js') }}指示资产助手通过调用require_asset($asset)来包含这个模板所需的css和js。

通常情况下,如果在分支之外完成,输出函数将在需要所有所需资产之后最后调用。

我遇到的问题与twig模板中这些函数的执行顺序有关。由于基地。首先调用Twig,并包含对输出函数的调用,这些函数在从扩展模板或包含的块/宏做出任何需求之前被调用。因此,结果是空的,没有考虑到这些新的要求。

我想到的解决这个问题的一种方法是在Twig返回渲染后计算输出,并在返回的结果中替换它们。这是可行的,但我觉得不够优雅。

我想知道是否有一种方法可以推迟{{ Assets.headAssets }}{{ Assets.bottomAssets }}的执行,直到twig完成其他所有事情。我有什么办法做到这一点吗?

对于那些还在寻找答案的人,我写了一个允许延迟块渲染的Twig扩展

我想这样可以:

base.twig

{% set bodyContent %}
    {% block body %}{% endblock body %}
{% endset %}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>{{ title }}</title>
        <!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
        {{ Assets.headAssets }}
    </head>
    </body>
        {{ bodyContent }}
        {{ Assets.bottomAssets }}
    <body>
</html>

其他文件可以不修改

正如你所看到的,block bodybase.twig模板中首先调用,所以当执行{{ Assets.headAssets }}调用时已经需要所有的资产。