extends
Тег extends может быть использован для расширения шаблона из другого шаблона.
Примечание
Как и PHP, Twig не поддерживает множественное наследование. Поэтому вы можете использовать только один тег extends за раз. Однако Twig поддерживает горизонтальное использование.
Определим базовый шаблон, base.html, который определяет простой HTML-скелет документа:
<!DOCTYPE html>
<html>
<head>
{% block head %}
<link rel="stylesheet" href="style.css"/>
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2011 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
</html>
В этом примере теги block определяют четыре блока, которые дочерние шаблоны могут заполнять.
Тег block просто сообщает движку шаблонов, что дочерний шаблон может переопределить эти части шаблона.
Дочерний шаблон
Дочерний шаблон может выглядеть так:
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ parent() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome on my awesome homepage.
</p>
{% endblock %}
Тег extends является ключевым моментом. Он сообщает движку шаблонов, что этот шаблон «расширяет» другой шаблон. Когда система шаблонов оценивает этот шаблон, она сначала находит родительский шаблон. Тег extends должен быть первым тегом в шаблоне.
Обратите внимание, что поскольку дочерний шаблон не определяет блок footer, вместо этого используется значение из родительского шаблона.
Вы не можете определить несколько тегов block с одинаковым именем в одном шаблоне. Это ограничение существует, потому что тег блока работает «в обоих» направлениях. То есть тег блока не только предоставляет место для заполнения, но также определяет содержимое, которое заполняет пустоту в родительском шаблоне. Если в шаблоне были два тега с одинаковым именем block, родительский шаблон не знал бы, какое из содержимого блоков использовать.
Если вы хотите вывести блок несколько раз, вы можете использовать функцию block:
<title>{% block title %}{% endblock %}</title>
<h1>{{ block('title') }}</h1>
{% block body %}{% endblock %}
Родительские блоки
Можно вывести содержимое родительского блока, используя функцию parent. Это возвращает результат родительского блока:
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ parent() }}
{% endblock %}
Именованные теги закрытия блоков
Twig позволяет помещать имя блока после тега закрытия для лучшей читаемости (имя после слова endblock должно совпадать с именем блока):
{% block sidebar %}
{% block inner_sidebar %}
...
{% endblock inner_sidebar %}
{% endblock sidebar %}
Вложенность и область видимости блоков
Блоки могут быть вложены для более сложных макетов. По умолчанию блоки имеют доступ к переменным из внешних областей видимости:
{% for item in seq %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}
Сокращения блоков
Для блоков с небольшим содержимым возможна сокращенная синтаксическая конструкция. Следующие конструкции делают то же самое:
{% block title %}
{{ page_title|title }}
{% endblock %}
{% block title page_title|title %}
Динамическое наследование
Twig поддерживает динамическое наследование, используя переменную в качестве базового шаблона:
{% extends some_var %}
Если переменная вычисляется как \Twig\Template или \Twig\TemplateWrapper экземпляр, Twig будет использовать её как родительский шаблон:
// {% extends layout %}
$layout = $twig->load('some_layout_template.twig');
$twig->display('template.twig', ['layout' => $layout]);
Вы также можете предоставить список шаблонов, которые проверяются на существование. Первый существующий шаблон будет использован как родительский:
{% extends ['layout.html', 'base_layout.html'] %}
Условное наследование
Поскольку имя шаблона для родительского шаблона может быть любым допустимым выражением Twig, можно сделать механизм наследования условным:
{% extends standalone ? "minimum.html" : "base.html" %}
В этом примере шаблон будет расширять шаблон макета «minimum.html», если переменная standalone вычисляется как true, и «base.html» в противном случае.
Как работают блоки?
Блок предоставляет способ изменить способ рендеринга определенной части шаблона, но не влияет на логику вокруг него.
Рассмотрим следующий пример, чтобы проиллюстрировать, как работает блок и, что важнее, как он не работает:
{# base.twig #}
{% for post in posts %}
{% block post %}
<h1>{{ post.title }}</h1>
<p>{{ post.body }}</p>
{% endblock %}
{% endfor %}
Если вы отобразите этот шаблон, результат будет точно таким же с тегом block или без него. Тег block внутри цикла for просто делает его переопределяемым дочерним шаблоном:
{# child.twig #}
{% extends "base.twig" %}
{% block post %}
<article>
<header>{{ post.title }}</header>
<section>{{ post.text }}</section>
</article>
{% endblock %}
Теперь, при рендеринге дочернего шаблона, цикл будет использовать блок, определённый в дочернем шаблоне, а не в базовом; выполненный шаблон будет эквивалентен следующему:
{% for post in posts %}
<article>
<header>{{ post.title }}</header>
<section>{{ post.text }}</section>
</article>
{% endfor %}
Рассмотрим другой пример: блок, включенный в оператор if:
{% if posts is empty %}
{% block head %}
{{ parent() }}
<meta name="robots" content="noindex, follow">
{% endblock head %}
{% endif %}
В отличие от того, что вы могли бы подумать, этот шаблон не определяет блок условно; он просто делает выводимое значение, которое будет отображено, когда условие true переопределяемым дочерним шаблоном.
Если вам нужно отображать вывод условно, используйте следующее вместо этого:
{% block head %}
{{ parent() }}
{% if posts is empty %}
<meta name="robots" content="noindex, follow">
{% endif %}
{% endblock head %}
© 2009–2018 by the Twig Team
Licensed under the three clause BSD license.
The Twig logo is © 2010–2020 Symfony
https://twig.symfony.com/doc/2.x/tags/extends.html