Содержание

Компиляция и выполнение шаблона. Активные компоненты шаблона. Дерево контекстов.

Цели и задачи раздела

Цель - дать необходимые знания о том, как работает шаблонизатор WACT:

Предполагается, что вы уже имеете небольшой опыт работы с WACT, например, выполнили самостоятельно базовый туториал, хотя это не обязательно. Мы рекомендуем вам прочтение данного раздела в любом случае, в целях ознакомления с механизмом работы WACT-а.

Если что-то здесь покажется вам немного непонятным или сложным - не беспокойтесь. Самое важное, чтобы после прочтения вы имели начальное представление о дереве контейнеров данных (иначе - контексты), из которых состоит шаблон во время его работы. Эти знания потребуются чтобы эффективно использовать "Выражения" и легко оперировать данными внутри шаблона (например, передавать данные с уровня на уровень).

Фаза компиляции и фаза исполнения шаблонов

Шаблонизатор WACT - является компилирующим обработчиком. То есть на основе базового шаблона создается php-скрипт, который записывается на диск, затем этот скрипт подключается и исполняется. Это дает значительное преимущество в скорости работы ввиду того, что php-скрипт создается только 1 раз и затем только исполняется, а также в том, что скомпилированные шаблоны могут кэшироваться php-акселераторами, например, eAccelerator.

Другими словами WACT шаблоны обрабатываются в 2 стадии

Так как фаза компиляции является достаточно «тяжелой» с точки зрения скорости выполнения, при помощи опции файла wact.conf.php (или settings.ini, если используете только WACT без WEB_APP пакета) вы можете отменить фазу компиляции. О том как это сделать см. раздел «Рендеринг WACT шаблона».

Обычно фаза компиляции нужна только в то время, когда вы создаете шаблон, во время разработки приложения, то есть тогда, когда шаблон активно исправляется. На рабочей же копии приложения, компиляцию отключают. То есть шаблонная система, однажды скомпилировав шаблон, уже не будет делать это повторно.

Скомпилированные шаблоны хранятся обычно в папке /var/compiled вашего приложения

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

Во время компиляции шаблон разбирается, и создается дерево тегов, наподобие DOM. Элементы этого дерева называются элементами (нодами) дерева компиляции (CompileTreeNode). Фильтры, выражения и предопределенные свойства также являются элементами этого дерева.

WACT предоставляет широкие возможности по повторному использование шаблонов:

Это накладывает свой отпечаток на процесс компиляции. WACT шаблон компилируется всегда только целиком. Это очень важно понимать! Поясним: если шаблон является составным, то есть включает другие шаблоны или же сам включается в другой шаблон, то компиляция производится в 2 этапа:

  1. сначала создается общий шаблон,
  2. потом общий шаблон компилируется

На самом деле это процесс немного сложнее, однако на данном этапе можно понимать компиляцию именно так. Подробнее об этом в разделе "Композиция шаблонов".

Из-за этих особенностей WACT не может поддерживать режим перекомпиляции при изменении только базового шаблона, как это имеет место в Smarty - ведь любая часть составного шаблона может быть изменена, а проверять все составляющие слишком накладно.

После сборки дерева производится обход всех его элементов (тегов, выражений, фильтров), каждый из которых выдает свою порцию php-скрипта откомпилированного шаблона.

Откомпилированный шаблон - это WACT шаблон переведенный в обычный, готовый к запуску php-скрипт, содержащий 2 функции:

Работа с шаблоном. Выполнение шаблона.

После того, как шаблонизатор откомпилировал шаблон, он сразу же вызывает инициализирующую функцию, которая создает в памяти дерево активных компонентов фазы исполнения (RuntimeComponentTree). К любому элементу этого дерева вы можете получить доступ через API шаблонной системы, что позволяет контролировать поведение этих компонентов, например, передавать в них данные, менять состояния и т.д:

Шаблон:

<body>
<h1>Newsline</h1>
 
<list:LIST id="news">     
<ul>     
  <list:ITEM>
    <li>[{$date}] <b>{$title}</b> </li>
  </list:ITEM>
</ul>
</list:LIST>
</body>

И код, который использует этот шаблон:

$template = new WactTemplate('news.html');
 
$list = $template->findChild('news');
 
$list->registerDataset($some_news_data);
 
$template->display();

То есть, вы из скрипта ставите данные или еще каким-либо образом модифицируете состояние компонентов фазы исполнения, а затем вызываете метод WactTemplate :: display(). В результате выполняется вторая, исполняющая фунция php-скрипта шаблона, и результат выводится в output-буфер.

Типы тегов. Связь тегов и компонентов фазы исполнения

Теперь мы покажем, какие типы тегов поддерживает WACT и связь между тегами начального шаблона и активными компонентами, доступными после компиляции.

Не волнуйтесь, если что-то покажется непонятным. Что именно необходимо уяснить:

WACT поддерживает теги нескольких видов:

Более глубокие знания по типам тегов можно найти в разделе "Типы тегов шаблонизатора WACT". Этот раздел может заинтересовать вас в будущем, когда вы захотите создавать свои теги.

Для нас сейчас не так важны все эти типы тегов, главное - это то, что некоторым тегам соответствуют активные компоненты.

Активные компоненты фазы исполнения соответствуют тегам первоначального шаблона. Например:

<core:datasource id='parent'>
 
  Название раздела: {$title}
 
  <fetch id='fetcher' using='MyFetcher' target='items' />
 
  <list:list id='items'>
   <ul>
     <list:item>
       <li>{$id} - {$title}</li>
     </list:item>
   </ul>
  </list:list>
</core:datasource>

После компиляции этого шаблона, мы получим следующее дерево активных компонентов:

root
|
`parent
 |
 |-fetcher
 |
 `-items

Сам шаблон является корневым компонентом (root). Он включает дочерний элемент parent. Элемент parent содержит два дочерних элемента fetcher и items.

Шаблон позволяет получать доступ к активным компонентам и манипулировать ими, например:

$parent_component = $template->findChild('parent'); // Вернет компонент, соответствующий тегу <core:datasource id='parent'>
$parent_component->registerDatasource(array('title' => 'My folder'));
$list_component = $parent_component->findChild('items'); // Вернет компонент, соответствующий тегу <list:list id='items'>
$list_component->registerDataset(array(array('title' => 'Sub1', 'id' => '10'),
                                       array('title' => 'Sub2', 'id' => '11')));
 
// А можно и сразу
$list_component = $template->findChild('items'); // ... если элемент с id='items' только 1 в шаблоне
$list_component->registerDataset(array(...));
 
// Или даже
$template->setChildDataSet('items', array(...));

Базовое понятие контекстов данных.

WACT при выводе или определении атрибутов тегов на этапе выполнения может брать данные из php-переменных, определенных в шаблоне или из так называемых контекстов. Контекст - это объект, из которого выражения берут данные в данном месте шаблона. Контекст можно понимать как обычный ассоциативный массив (массив вида ключ ⇒ значение). Иногда вместо контекста мы используем в документации термин «простой контейнер данных» или просто «контейнер данных».

Контексты - самая спорная и самая сложная часть WACT-шаблонизатора. Они - основная причина появлении идеи о разработке альтернативной шаблонной системы MACRO, которая будет |отличаться по некоторым ключевым признакам от WACT-а.

На основе предущего примера мы покажем отличия между различными активными компонентами.

Обратите внимание, что для передачи данных в обычный контекст используется метод registerDatasource(), а в списковый контейнер данных - registerDataset().

Выражения вида {$title} всегда применяются к текущему контексту. То есть если бы мы написали:

<core:datasource id='parent'>
 
  <fetch id='fetcher' using='MyFetcher' target='items' />
 
  <list:list id='items'>
  Название раздела: {$title}
 
   <ul>
     <list:item>
       <li>{$id} - {$title}</li>
     </list:item>
   </ul>
  </list:list>
</code:datasource>

то выражение {$title} внутри <list:list> обратился все равно к контейнеру тега <core:datasource>. А вот {$title} и {$id} внутри <list:item> уже обращаются к контейнеру данных тега <list:item>.

Теги, которым соответствуют контексты (обычные контейнеры данных):

Теги, которым соответствуют списковые контейнеры данных:

Дерево контекстов

Так как активные компоненты образуют дерево, значит и контексты также образуют дерево.

Корень дерева - корневой активный компонент (root - сам шаблон) также является корневым контекстом.

Модификаторы в выражениях

Знание иерархии контекстов позволяет понимать, к чему относится то или иное выражение, если в нем используются так называемые модификаторы, например:

Подробнее о модификаторах в разделе "Data Binding Expressions".

Дополнительная информация