在Twig中有条件地扩展模板

时间:2017-05-15 08:57:41

标签: php twig template-engine

采用以下树形结构:

├───base
│   ├───0001
│   │   └───pages
│   │           file.twig
│   │           file_content.twig
│   └───ext
│       └───store
│       │   └───pages
│       │       └───all
│       │       │       file.twig
│       │       └───0001
│       │               file.twig
│       └───newsletter
│           └───pages
│               └───all
│               │       file.twig
│               └───0001
│                       file.twig
└───pages
    │   file.twig
    └───0001
            file.twig

正如你所看到的那样,file.twig散布着。{/ p>

我想渲染文件base/0001/pages/file_content.twig的内容 但是,我希望以下文件可以更改块内的内容:

  • ext/<...>/pages/0001/file.twig
  • ext/<...>/pages/all/file.twig
  • /pages/0001/file.twig
  • /pages/file.twig

但是,这些文件可能存在也可能不存在,可能需要也可能不需要,并且必须能够更改任何块的内容。

有没有办法让这项工作?

到目前为止,我有以下内容:

{% embed 'base/pages/file_content.twig' %}
    {% block page_file %}
        {{ parent() }}
        {% if data.store_enabled %}
            {% include [
                    'base/ext/store/pages/0001/file.twig',
                    'base/ext/store/pages/all/file.twig'
                ] ignore missing
            %}
        {% endif %}
        {% include ['pages/0001/file.twig', 'pages/file.twig'] ignore missing %}
    {% endblock %}
{% endembed %}

这是“有效”的,因为它呈现页面但不允许任何块被覆盖。

我怎样才能做到这一点?

作为一个例子,考虑一下这种文件结构(是的,文件丢失,这是预期的):

    ├───base
    │   ├───0001
    │   │   └───pages
    │   │           file.twig
    │   │           file_content.twig
    │   └───ext
    │       └───store
    │       │   └───pages
    │       │       └───0001
    │       │               file.twig
    └───pages
            file.twig

文件base/0001/pages/file_content.twig具有以下内容:

{% block page_file %}
    {% block title %}<h1>Nice title</h1>{% endblock %}
    {% block price %}{% endblock %}
    <div class="clearfix"></div>
{% endblock %}

文件base/ext/store/pages/0001/file.twig具有以下内容:

{% block price %}<span class="price">55 &euro;</span>{% endblock %}

文件pages/file.twig包含:

{% block title %}{{ parent() }}<hr>{% endblock %}
{% block price %}<div>{{ parent() }}</div>{% endblock %}

我期望的输出如下:

<h1>Nice title</h1><hr>
<div><span class="price">55 &euro;</span</div>
<div class="clearfix"></div>

但是使用该代码,所有其他文件的更改都被忽略,输出只有以下内容:

<h1>Nice title</h1>
<div class="clearfix"></div>

注意:

重要的是要注意我正在使用Twig 1.33.2,并使用Twig_Autoloader::register();方法。

我不能使用Twig 2.x,因为它需要PHP 7.0+而我只限于PHP 5.3.29。

1 个答案:

答案 0 :(得分:0)

经过几次尝试之后,我终于找到了办法。

这看起来很丑陋......

假设结构:

├───base
│   ├───0001
│   │   └───pages
│   │           file.twig
│   │           file_content.twig
│   └───ext
│       └───store
│       │   └───pages
│       │       └───0001
│       │               file.twig
└───pages
        file.twig

主文件(base/pages/file.twig)包含以下代码:

{% if data.store_enabled %}
    {% include [
            'base/ext/store/pages/0001/file.twig',
            'base/ext/store/pages/all/file.twig',

            'base/pages/file_content.twig'
        ] ignore missing
    %}
{% else %}
    {% include [
            'pages/0001/file.twig',
            'pages/file.twig',

            'base/pages/file_content.twig'
        ] ignore missing
    %}
{% endif %}

这将包括base/ext/store/pages/内的文件(如果存在)。如果文件丢失,则包含文件base/pages/file_content.twig

base/ext/store/pages/内的所有文件顶部必须包含以下代码:

{% extends [
        'pages/0001/file.twig',
        'pages/file.twig',

        'base/pages/file_content.twig'
    ]
%}

pages/内的文件必须包含以下内容:

{% extends 'base/pages/file_content.twig' %}

这允许您在base/pages/file_content.twig内覆盖任何块,并且只有文件存在时才会包含/扩展。

有一个保证文件(在这种情况下,base/pages/file_content.twig 必须始终存在)仍将显示“默认”内容,并且不会引发令人讨厌的异常。

除了这个答案的范围之外,我最初发现了一个非常相似的方法,它使用了条件值。

试一试:https://twigfiddle.com/u06tur

相关问题