在 Twig 中有条件地扩展模板
Extend template conditionally in Twig
取下面的树结构:
├───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
。
我想渲染文件的内容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 %}
这个 "works",在某种意义上它呈现页面但不允许覆盖任何块。
我怎样才能完成这项工作?
例如,考虑这种文件结构(是的,文件丢失,这是预期的):
├───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 €</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 €</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.
经过多次尝试,我终于想出了一个办法。
这看起来很丑...
假设结构:
├───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
中覆盖 any 块并且文件只有 included/extended 如果它们存在。
有保证文件(在这种情况下,base/pages/file_content.twig
必须 始终存在)仍将显示 "default" 内容并且不会抛出讨厌的例外。
在这个答案的范围之外,我最初发现了一个非常相似的方法,它使用了条件值。
取下面的树结构:
├───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
。
我想渲染文件的内容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 %}
这个 "works",在某种意义上它呈现页面但不允许覆盖任何块。
我怎样才能完成这项工作?
例如,考虑这种文件结构(是的,文件丢失,这是预期的):
├───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 €</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 €</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.
经过多次尝试,我终于想出了一个办法。
这看起来很丑...
假设结构:
├───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
中覆盖 any 块并且文件只有 included/extended 如果它们存在。
有保证文件(在这种情况下,base/pages/file_content.twig
必须 始终存在)仍将显示 "default" 内容并且不会抛出讨厌的例外。
在这个答案的范围之外,我最初发现了一个非常相似的方法,它使用了条件值。