====== Композиция шаблонов: включение(include), обворачивание(wrap) и переиспользование(reuse) шаблонов ======
===== Компиляция MACRO шаблонов =====
MACRO содержит различные средства, которые позволяют собирать конечные шаблоны из набора других шаблонов:
* **Включение (include)** - включение одного шаблона в другой.
* **Обворачивание (wrap)** - обворачивание одного шаблона другим.
* **Переиспользование (reuser)** - использование части текущего шаблона несколько раз в различных местах.
**MACRO компилирует шаблоны только целиком!** То есть сначала обрабатываются все теги, такие как {{include}}, {{wrap}}, {{into}}, {{apply}} , и только затем окончательно создается откомпилированный шаблон. Именно поэтому разбиение шаблона на составляющие в MACRO с точки зрения выполнения конечного шаблона ничего не стоит (лишь увеличивается время компиляции). Это дает нам возможность выносить в отдельные шаблоны все, что повторяется в нескольких файлах.
Цель данной страницы - показать способы "снижения дублирования" в MACRO-шаблонах, то есть как максимально эффективно использовать все возможности MACRO по композиции шаблонов.
===== Включение (include). Использование тега {{include}} =====
Включение (include) одного шаблона в другой. Include в MACRO осуществляется посредством [[limb3_2007_4:ru:packages:macro:tags:core_tags:include_tag|тега {{include}}]]. По-умолчанию, включаемый файл компилируется как обычный шаблон.
{{include file='header.html'}}
[...content...]
{{include file='footer.html'}}
Если вы используете MACRO совместно с пакетом VIEW, и в атрибуте file используется абсолютное значение (начинается с **/** или с **c:/**), тогда MACRO подключает шаблон по абсолютному пути. В противном случае - пытается найти шаблон через механизм подключения шаблонов.
Стоит также обратить внимание, что при включении шаблона включаемый шаблон должен быть сбалансированным с точки зрения MACRO-тегов. То есть если тег предусматривает закрывающий тег, например, тег {{list}} или {{pager}}, значит и закрываться он должен в том же файле.
===== Обворачивание (wrap) =====
==== Введение в обворачивание шаблонов ====
Обворачивание (wrap) - это вставка шаблона в определенное место другого шаблона.
С обворачиванием шаблонов связаны следующие термины:
* Текущий шаблон - который содержит команды по обворачиванию (в нем содержатся теги {{wrap}})
* Базовый шаблон - в который осуществляется вставка текущего шаблона.
* Контейнер вставки или слот (slot/placeholder) - находится в базовом шаблоне и помечает места вставки.
Обворачивание производится при помощи [[limb3_2007_4:ru:packages:macro:tags:core_tags:wrap_tag|тега {{wrap}}]]. Слот для вставки помечается в базовом шаблоне [[limb3_2007_4: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_2007_4:ru:packages:macro:tags:core_tags:wrap_tag|тег {{wrap}}]]. {{wrap}} требует закрывающего тега. Обворачиваемой считается та часть текущего шаблона, что обрамлена в рамки тега {{wrap}}.
По-умолчанию {{wrap}} вставляет все свое содержимое в слот, указаный при помощи атрибута **into**.
Однако можно различные части текущего шаблона отправить в различные слоты базового шаблона. Для этого используется [[limb3_2007_4: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_2007_4:ru:packages:macro:tags:core_tags:template_tag|тега {{template}}]] и нескольких [[limb3_2007_4: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}} - это по сути отдельный локальный контекст и локальные переменные в нем будут не видны, и их нужно туда передавать, что и реализовано в приведенном примере.