====== Композиция шаблонов: включение(include), обворачивание(wrap) и переиспользование(reuse) шаблонов ======
===== Компиляция MACRO шаблонов =====
MACRO содержит различные средства, которые позволяют собирать конечные шаблоны из набора других шаблонов:
* **Включение (include)** - включение одного шаблона в другой.
* **Обворачивание (wrap)** - обворачивание одного шаблона другим.
* **Переиспользование (reuse)** - использование части текущего шаблона несколько раз в различных местах.
**MACRO компилирует шаблоны только целиком!** То есть сначала обрабатываются все теги, такие как [[limb3:ru:packages:macro:tags:core_tags:include_tag| {{include}}]], [[limb3:ru:packages:macro:tags:core_tags:wrap_tag| {{wrap}}]], [[limb3:ru:packages:macro:tags:core_tags:into_tag| {{into}}]], [[limb3:ru:packages:macro:tags:core_tags:apply_tag| {{apply}}]] , и только затем окончательно создается откомпилированный шаблон. Именно поэтому разбиение шаблона на составляющие в MACRO с точки зрения выполнения конечного шаблона ничего не стоит (лишь увеличивается время компиляции). Это дает нам возможность выносить в отдельные шаблоны все, что повторяется в нескольких файлах.
Цель данной страницы - показать способы "снижения дублирования" в MACRO-шаблонах, то есть как максимально эффективно использовать все возможности MACRO по композиции шаблонов.
===== Включение (include). Использование тега {{include}} =====
Включение (include) одного шаблона в другой. Include в MACRO осуществляется посредством [[limb3:ru:packages:macro:tags:core_tags:include_tag|тега {{include}}]]. По-умолчанию, включаемый файл компилируется как обычный шаблон.
{{include file='header.phtml'}}
[...content...]
{{include file='footer.phtml'}}
Если вы используете MACRO совместно с пакетом VIEW, и в атрибуте file используется абсолютное значение (начинается с **/** или с **c:/**), тогда MACRO подключает шаблон по абсолютному пути. В противном случае - пытается найти шаблон через механизм подключения шаблонов.
Стоит также обратить внимание, что при включении шаблона включаемый шаблон должен быть сбалансированным с точки зрения MACRO-тегов. То есть если тег предусматривает закрывающий тег, например, тег [[limb3:ru:packages:macro:tags:list_tags:list_tag| {{list}}]] или [[limb3:ru:packages:macro:tags:pager_tags:pager_tag| {{pager}}]], значит и закрываться он должен в том же файле.
===== Обворачивание (wrap) =====
==== Введение в обворачивание шаблонов ====
Обворачивание (wrap) -- это вставка текущего шаблона в определенное место другого шаблона.
С обворачиванием шаблонов связаны следующие термины:
* Текущий шаблон -- который содержит команды по обворачиванию (в нем содержатся теги [[limb3:ru:packages:macro:tags:core_tags:wrap_tag| {{wrap}}]])
* Базовый шаблон -- в который осуществляется вставка текущего шаблона.
* Контейнер вставки или слот (slot/placeholder) -- находится в базовом шаблоне и помечает места вставки.
Обворачивание производится при помощи [[limb3:ru:packages:macro:tags:core_tags:wrap_tag|тега {{wrap}}]]. Слот для вставки помечается в базовом шаблоне [[limb3:ru:packages:macro:tags:core_tags:slot_tag|тегом {{slot}}]].
Рассмотрим небольшой пример:
**page.html** -- базовый шаблон
[...meta...]
{{slot id='content'/}}
**my_page.html** -- текущий шаблон
{{wrap with='page.html' into='content'}}
[...content...]
{{/wrap}}
В результате получим нечто:
[...meta...]
[...content...]
==== Использование тега {{wrap}}. Множественное обворачивание. Тег {{into}} ====
Разберем подробнее, как работает [[limb3:ru:packages:macro:tags:core_tags:wrap_tag|тег {{wrap}}]]. %%{{wrap}}%% требует закрывающего тега. Обворачиваемой считается та часть текущего шаблона, что обрамлена в рамки тега %%{{wrap}}%%.
По-умолчанию %%{{wrap}}%% вставляет все свое содержимое в слот, указаный при помощи атрибута **into**.
Однако можно различные части текущего шаблона отправить в различные слоты базового шаблона. Для этого используется [[limb3:ru:packages:macro:tags:core_tags:into_tag|тег {{into}}]].
Поясним это все на примере:
Допустим есть базовый шаблон страницы page.html:
{{slot id='content'/}}
Также шаблон дополнительного дизайна layout.html с двумя местами для вставки (как бы второй базовый шаблон):
{{slot id='main'/}}
И теперь текущий шаблон display.html:
{{wrap with='page.html' into='content'}}
{{wrap file='layout.html'}}
{{into slot='header'}}My Header{{/into}}
{{into slot='main'}}My Complex content{{/into}}
{{/wrap}}
{{/wrap}}
На выходе получим:
My Complex content
Необходимо пояснить, как именно компилируется шаблон в данном случае. Сначала обрабатывается первый %%{{wrap}}%% и мы получаем на 1-м шаге компиляции следующий шаблон:
{{wrap with='layout.html'}}
{{into slot='header'}}My Header{{/into}}
{{into slot='main'}}My Complex content{{/into}}
{{/wrap}}
Затем обрабатывается второй %%{{wrap}}%% и условно получается:
{{slot id='main'/}}
{{into slot='header'}}My Header{{/into}}
{{into slot='main'}}My Complex content{{/into}}
В результате работы тегов %%{{into}}%% получается конечный результат.
Если %%{{into}}%% тег находит вне %%{{wrap}}%% тега, тогда он пытается найти соответстувующий тег %%{{slot}}%% начиная с корня дерева компилируемого шаблона.
===== Повторное использование части текущего шаблона =====
Представим, что вам необходимо вывести 2 списка элементов одинакомым образом, однако имеющим различные источники данных. Например, на первой странице раздела нам нужно вывести лучшие товары и остальные товары раздела.
Первое решение - это вынести повторяющуюся часть шаблона в отдельный файл и подключать его 2 раза при помощи тега %%{{include}}%%. Это хороший вариант, если вы собираетесь использовать этот выделенный шаблон несколько раз еще в других шаблонах.
Если же общая часть используется только в рамках одного шаблона, то этих целей целесообразно использовать комбинацию [[limb3:ru:packages:macro:tags:core_tags:template_tag|тега {{template}}]] и нескольких [[limb3:ru:packages:macro:tags:core_tags:apply_tag|тегов {{apply}}]].
Например:
{{template name="photo_tpl"}}
{$item.ctime|date:"d.m.Y"}
{$item.title}
{$item.member.nick}
предварительный просмотр
{{/template}}
Лучшие фото рубрики {$#category.title}
{{list using="$#best_photos" as="$photo"}}
{{list:item}}
- {{apply template="photo_tpl" item="$photo"/}}
{{/list:item}}
{{/list}}
Все фото рубрики {$#category.title}
{{list using="$#photos" as="$photo"}}
{{list:item}}
- {{apply template="photo_tpl" item="$photo"/}}
{{/list:item}}
{{/list}}
Сам тег %%{{template}}%% ничего не рендерит. Только вызовы %%{{apply}}%% вставляют часть этого кода в нужное место. Обратите внимание, что на уровне откомплированного шаблона %%{{template}}%% создает отдельный метод, а %%{{apply}}%% - это по сути вызов этого метода. Поэтому то, что находится в рамках %%{{template}}%% - это по сути отдельный локальный контекст и локальные переменные в нем будут не видны, и их нужно туда передавать, что и реализовано в приведенном примере.