Инструменты пользователя

Инструменты сайта


limb3:ru:packages:macro:template_composition

Композиция шаблонов: включение(include), обворачивание(wrap) и переиспользование(reuse) шаблонов

Компиляция MACRO шаблонов

MACRO содержит различные средства, которые позволяют собирать конечные шаблоны из набора других шаблонов:

  • Включение (include) - включение одного шаблона в другой.
  • Обворачивание (wrap) - обворачивание одного шаблона другим.
  • Переиспользование (reuse) - использование части текущего шаблона несколько раз в различных местах.

MACRO компилирует шаблоны только целиком! То есть сначала обрабатываются все теги, такие как {{include}}, {{wrap}}, {{into}}, {{apply}} , и только затем окончательно создается откомпилированный шаблон. Именно поэтому разбиение шаблона на составляющие в MACRO с точки зрения выполнения конечного шаблона ничего не стоит (лишь увеличивается время компиляции). Это дает нам возможность выносить в отдельные шаблоны все, что повторяется в нескольких файлах.

Цель данной страницы - показать способы «снижения дублирования» в MACRO-шаблонах, то есть как максимально эффективно использовать все возможности MACRO по композиции шаблонов.

Включение (include). Использование тега {{include}}

Включение (include) одного шаблона в другой. Include в MACRO осуществляется посредством тега {{include}}. По-умолчанию, включаемый файл компилируется как обычный шаблон.

{{include file='header.phtml'}}
[...content...]
{{include file='footer.phtml'}}

Если вы используете MACRO совместно с пакетом VIEW, и в атрибуте file используется абсолютное значение (начинается с / или с c:/), тогда MACRO подключает шаблон по абсолютному пути. В противном случае - пытается найти шаблон через механизм подключения шаблонов.

Стоит также обратить внимание, что при включении шаблона включаемый шаблон должен быть сбалансированным с точки зрения MACRO-тегов. То есть если тег предусматривает закрывающий тег, например, тег {{list}} или {{pager}}, значит и закрываться он должен в том же файле.

Обворачивание (wrap)

Введение в обворачивание шаблонов

Обворачивание (wrap) – это вставка текущего шаблона в определенное место другого шаблона.

С обворачиванием шаблонов связаны следующие термины:

  • Текущий шаблон – который содержит команды по обворачиванию (в нем содержатся теги {{wrap}})
  • Базовый шаблон – в который осуществляется вставка текущего шаблона.
  • Контейнер вставки или слот (slot/placeholder) – находится в базовом шаблоне и помечает места вставки.

Обворачивание производится при помощи тега {{wrap}}. Слот для вставки помечается в базовом шаблоне тегом {{slot}}.

Рассмотрим небольшой пример:

page.html – базовый шаблон

<html>
<head>
[...meta...]
</head>
<body>
 {{slot id='content'/}}
</body>
</html>

my_page.html – текущий шаблон

{{wrap with='page.html' into='content'}}
[...content...]
{{/wrap}}

В результате получим нечто:

<html>
<head>
[...meta...]
</head>
<body>
 [...content...]
</body>
</html>

Использование тега {{wrap}}. Множественное обворачивание. Тег {{into}}

Разберем подробнее, как работает тег {{wrap}}. {{wrap}} требует закрывающего тега. Обворачиваемой считается та часть текущего шаблона, что обрамлена в рамки тега {{wrap}}.

По-умолчанию {{wrap}} вставляет все свое содержимое в слот, указаный при помощи атрибута into.

Однако можно различные части текущего шаблона отправить в различные слоты базового шаблона. Для этого используется тег {{into}}.

Поясним это все на примере:

Допустим есть базовый шаблон страницы page.html:

<html>
<body>
  {{slot id='content'/}}
</body>
</html>

Также шаблон дополнительного дизайна layout.html с двумя местами для вставки (как бы второй базовый шаблон):

 <div id='header'>{{slot id='header'/}}</div>
 <div id='main'>{{slot id='main'/}}</div>

И теперь текущий шаблон 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}}

На выходе получим:

<html>
<body>
  <div id='header'>My Header</div>
  <div id='main'>My Complex content</div>
</body>
</html>

Необходимо пояснить, как именно компилируется шаблон в данном случае. Сначала обрабатывается первый {{wrap}} и мы получаем на 1-м шаге компиляции следующий шаблон:

<html>
<body>
  {{wrap with='layout.html'}}
   {{into slot='header'}}My Header{{/into}}
   {{into slot='main'}}My Complex content{{/into}}
  {{/wrap}}
</body>
</html>

Затем обрабатывается второй {{wrap}} и условно получается:

<html>
<body>
 
 <!-- Дочерние {{into}} теги сначала ищут контейнеры вставки в этих рамках -->
 <div id='header'>{{slot id='header'/}}</div>
 <div id='main'>{{slot id='main'/}}</div>
 
 {{into slot='header'}}My Header{{/into}}
 {{into slot='main'}}My Complex content{{/into}}
 <!-- ...... -->
 
</body>
</html>

В результате работы тегов {{into}} получается конечный результат.

Если {{into}} тег находит вне {{wrap}} тега, тогда он пытается найти соответстувующий тег {{slot}} начиная с корня дерева компилируемого шаблона.

Повторное использование части текущего шаблона

Представим, что вам необходимо вывести 2 списка элементов одинакомым образом, однако имеющим различные источники данных. Например, на первой странице раздела нам нужно вывести лучшие товары и остальные товары раздела.

Первое решение - это вынести повторяющуюся часть шаблона в отдельный файл и подключать его 2 раза при помощи тега {{include}}. Это хороший вариант, если вы собираетесь использовать этот выделенный шаблон несколько раз еще в других шаблонах.

Если же общая часть используется только в рамках одного шаблона, то этих целей целесообразно использовать комбинацию тега {{template}} и нескольких тегов {{apply}}.

Например:

  {{template name="photo_tpl"}}
    <span class="date">{$item.ctime|date:"d.m.Y"}</span>
    <a href="/photo/item/{$item.id}" class="img"><img alt="{$item.title}" src="{$item.icon_file_url}"></a>
    <a href="/photo/item/{$item.id}" class="title">{$item.title}</a>
    <a href="#" class="author">{$item.member.nick}</a>
    <a href="{$item.thumbnail_file_url}" title="{$item.title}" class='preview'>предварительный просмотр</a>
  {{/template}}
 
  <h2>Лучшие фото рубрики {$#category.title}</h2>
  {{list using="$#best_photos" as="$photo"}}
  <ul id='best_photos_list'>
    {{list:item}}
     <li>{{apply template="photo_tpl" item="$photo"/}}</li>
    {{/list:item}}
  </ul>
  {{/list}}
 
  <h2>Все фото рубрики {$#category.title}</h2>
  {{list using="$#photos" as="$photo"}}
  <ul id='photos_list'>
    {{list:item}}
     <li>{{apply template="photo_tpl" item="$photo"/}}</li>
    {{/list:item}}
  </ul>
  {{/list}}

Сам тег {{template}} ничего не рендерит. Только вызовы {{apply}} вставляют часть этого кода в нужное место. Обратите внимание, что на уровне откомплированного шаблона {{template}} создает отдельный метод, а {{apply}} - это по сути вызов этого метода. Поэтому то, что находится в рамках {{template}} - это по сути отдельный локальный контекст и локальные переменные в нем будут не видны, и их нужно туда передавать, что и реализовано в приведенном примере.

Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
  __  __  ____   ____ ______   __ __
 / / / / /_  /  /  _//_  __/  / // /
/ /_/ /   / /_ _/ /   / /    / _  / 
\____/   /___//___/  /_/    /_//_/
 
limb3/ru/packages/macro/template_composition.txt · Последние изменения: 2010/11/10 10:02 (внешнее изменение)