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

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


limb3:ru:packages:wact:important_details

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

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

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

  • что такое компиляция шаблонов,
  • какие типы тегов поддерживаются,
  • что такое компоненты времени исполнения,
  • что такое контейнеры данных

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

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

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

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

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

  • фаза компиляции (CompileTime)
  • фаза исполнения (RunTime)

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

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

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

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

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

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

  • включение (include), то есть вставка другого шаблона в текущий шаблон и
  • обворачивание (wrap), то есть вставка текущего шаблона или его части внутрь другого шаблона.

Это накладывает свой отпечаток на процесс компиляции. 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 и связь между тегами начального шаблона и активными компонентами, доступными после компиляции.

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

  • некоторым тегам соответствуют активные компоненты,
  • эти активные компоненты объеденены в дерево,
  • некоторые из таких объектов являются контейнерами данных. Из контейнеров данных выводятся данные при помощи выражений вида {$title}

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

  • Теги, которые не имеют активного компонента:
    • WACT-теги, которые участвуют в процессе сборки шаблона. Это теги <core:include> и <core:wrap>.
    • WACT-теги, которые просто генерируют php-код в процессе компиляции шаблона. Например, <core:optional>, <core:repeat>, <core:default> и т.д.
  • Теги, которые имеют активный компонент:
    • WACT-теги, которые генерируют php-код. Например, <pager:navigator>, <core:block>, <fetch>, <active_record:fetch>, <iterator:transfer> и т.д.
    • HTML-теги, которые генерируют php-код. Например тэги <input>, <textarea> - обычно это теги элементов форм.
  • Теги с активным компонентом, которые является контейнером данных (контекстом):
    • WACT-теги, которые генерируют php-код. Это такие теги, как <core:datasource>, <list:list>, <list:item>.
    • HTML-теги, которые генерируют php-код. Например тег <form>.

Более глубокие знания по типам тегов можно найти в разделе "Типы тегов шаблонизатора 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-а.

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

  • Тегу <core:datasource> соответствует компонент, который является контекстом.
  • Тегу <fetch> соответствует активный компонент, который не является контекстом, но выполняет другую полезную работу. В данном случае получает данные и передает их в компонент <list:list> тега.
  • Тегу <list:list> соответствует компонент, который является списковым контейнером данных, но не является контекстом. <list:list> это источник данных для другого контекста - из тега <list:item>
  • Тегу <list:item> соответствует компонент, который является контекстом. Этот контейнер данных последовательно получает свои данные из компонента тега <list:list>.

Обратите внимание, что для передачи данных в обычный контекст используется метод 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 - сам шаблон) также является корневым контекстом.

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

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

  • {$title} - относится к текущему контексту.
  • {$^title} - относится к родительскому контексту (на 1 уровень выше, чем текущий).
  • {$^^title} - на 2 уровня выше, чем текущий.
  • {$#title} - относится к корневому контексту (root).

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

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

Обсуждение

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