Переопределение блоков в включенных шаблонах веток
Существует ли в целом "хороший" способ достижения этой функциональности? Я читал о теге "использовать", который пока кажется лучшим вариантом, но мне все еще не нравится, что он не позволяет мне вводить какой-либо внешний html, только блоки.
Я буду использовать тег "включить" в приведенном ниже примере, чтобы продемонстрировать намерение, которое я пытаюсь описать.
#base.html.twig
{% include 'elements/header.html.twig' %}
{% block content %}{% endblock %}
{% include 'elements/footer.html.twig' %}
#header.html.twig
<h1>This is my header</h1>
{% block page_title %} Default Page Title {% endblock %}
#index.html.twig
{% extends 'layouts/base.html.twig' %}
{# I want to be able to do this somehow #}
{% block page_title %} This is my overridden page title {% endblock %}
{% block content %} here is the index page content {% endblock %}
5 answers
Я нашел решение. Используйте функцию block(), чтобы получить содержимое дочернего блока и передать его в файл header.html.twig в качестве переменной в операторе include:
#base.html.twig
{% include 'elements/header.html.twig' with {page_title: block('page_title')} %}
{% block content %}{% endblock %}
{% include 'elements/footer.html.twig' %}
#header.html.twig
<h1>This is my header</h1>
{% if page_title is empty %}
Default Page Title
{% else %}
{{ page_title }}
{% endif %}
#index.html.twig
{% extends 'layouts/base.html.twig' %}
{% block page_title %} This is my overridden page title {% endblock %}
{% block content %} here is the index page content {% endblock %}
Проверьте тег встраивания: http://twig.sensiolabs.org/doc/tags/embed.html
Работает не совсем так, как вы хотите, но я думаю, что сейчас это настолько близко, насколько вы можете.
Я нашел хорошее и реальное решение, прочитав документацию для встраивать бирка. Я использую Twig 2.0 в Symfony 4.
Моя структура
#templates/base.html.twig
{% block navbar %}
<nav>
{% block menu %}
{% include '_menu' %}
{% endblock menu %}
</nav>
{% endblock navbar %}
{% block content %}
{# several blocks defined #}
{% block footer '' %}
{% endblock content %}
#templates/_menu.html.twig
<ul>
{% block sub_app_menu_itens %}
<li>Main App Menu Item</li>
{% endblock sub_app_menu_itens %}
<li>Menu item</li>
<li>Another menu item</li>
<li>Yet another menu item</li>
</ul>
С кодом выше, когда я создаю свой индекс.html.ветка единственный код, необходимый для отображения вещей по умолчанию, - это
#templates/index.html.twig
{% extends 'base.html.twig' %}
И переопределять определенные блоки.
Но, когда мне нужно создать другую страницу, которая использует этот скелет, если я попытаюсь переопределить блок sub_app_menu_itens в другом включенном шаблоне _partial не работает. <li>Main App Menu Item</li>
всегда отображается и никогда не перезаписывается (код выше)
#templates/subapp/index.html.twig
{% extends 'base.html.twig' %}
{% block title %}{{ 'agencia.homepage'|trans }}{% endblock %}
{% block menu %}
{% include 'subapp/_menu.html.twig' %}
{% endblock menu %}
{% block user_content %}Content Here{% endblock %}
#templates/subapp/_menu.html.twig
{% extends '_menu.html.twig' %}
{% block sub_app_menu_itens %}
<li>SubApp Menu Item</li>
{% endblock sub_app_menu_itens %}
<li>SubApp Menu Item</li>
никогда не показывается. Пробовал много вещей, таких как extends
и даже условные выражения, но безуспешно.
Решение
В встраивать тег решает проблему перезаписи дочерних блоков частичных шаблонов.
#templates/subapp/index.html.twig
{% block menu %}
{% embed '_menu.html.twig' %}
{% block sub_app_menu_itens %}
{% include 'subapp/_menu.html.twig' %}
{% endblock sub_app_menu_itens %}
{% endembed %}
{% endblock menu %}
И упрощение шаблона _partial, чтобы иметь только необходимый html
#templates/subapp/_menu.html.twig
<li>SubApp Menu Item</li>
Сейчас <li>SubApp Menu Item</li>
будет отображаться в нужном месте шаблона _menu.
Мышление на уровнях, include
работает как подуровень (анализируется), и все вещи переопределяются только на одном уровне, поэтому include
не позволяет переопределять в другом включении. Вместо этого шаблоны embed
выводятся на один и тот же уровень (не анализируются), и поэтому вы можете переопределять вещи.
Это можно сделать. Вот мое решение проблемы путем передачи переменной в представление.
#layout.twig
{% if sidebar is empty %}
This is the default sidebar text.
{% else %}
{% block sidebar %}{% endblock %}
{% endif %}
{% block content %}{% endblock %}
#index.twig
{% extends "layout.twig" %}
{% block sidebar %}
This is the sidebar. It will override the default text.
{% endblock %}
{% block content %}
This is the content.
{% endblock %}
#index.php (SlimPHP)
$app->render('index.twig', ['sidebar' => true]);
Поскольку я использую SlimPHP, я называю его так, передавая переменную sidebar
в представление. Это можно расширить, используя различные переменные, переданные в представление, чтобы вы могли выбрать sidebar1
, sidebar2
и т.д.
Я заставил его работать с очень простым взломом:
В основном он ведет себя таким образом, потому что без {% extends "foo.html.twig" %}
он не понимает блоки и просто отображает их на месте.
Итак, давайте расширим... ничего:
{% extends "nothing.html.twig" %}
Это ничто на самом деле всего лишь 1 блок:
# nothing.html.twig
{% block main %}
{% endblock %}
Единственное, что вам нужно, это завернуть все в блок, этот фальшивый "основной" блок.