Работа с шаблонами. Использование HTML::Template с CGI-скриптами.
 

Одной из частых задач стоящих перед Web-программистом является отделение логики получения данных от формата представления данных. Для решения такой задачи часто используют шаблоны html-документов, которые при работе программ заполняются данными. Это позволяет выполнять верстку страниц другому человеку, или изменять внешний вид страниц не изменяя саму программу.

CPAN предоставляет программисту выбор разных средств работы с шаблонами. Среди них: HTML::Template, Text::Template, Template toolkit. Как правило методика работы со всеми этими модулями одинакова. Программист создает объект, указывающий на нужный шаблон, затем формируется набор данных, для заполнения шаблона и выполняется само заполнение шаблона, а результат этого возвращается в виде готовой HTML страницы. Давайте подробнее рассмотрим модуль HTML::Template.

В отличии от других модулей, этот модуль ориентирован на то, что в качестве шаблонов будут использоваться страницы с HTML разметкой. Соответственно, директивы шаблона выглядят подобно HTML тэгам, не мешая HTML редакторам работать с разметкой страницы. С помощью этих директив можно заполнять шаблон разными данными, в зависимости от условных флагов; имитировать циклы, например при заполнении таблиц. При этом все конструкции можно использовать внутри друг друга, создавая шаблоны произвольной сложности.

HTML::Template также позволяет программисту контролировать работу с шаблонами. Например, при использовании данного модуля в сочетании с mod_perl можно использовать кэширование разобранных шаблонов и использовать результаты в разных скриптах. Кроме кэширования программист может задать фильтры, которые будут производить обработку сгенерированного текста. Все параметры шаблонов задаются при создании объекта, описывающего шаблон.

Создание объекта

Для работы с шаблоном необходимо сначала создать объект, который описывает выбранный шаблон. Создание объекта выполняется с помощью вызова оператора new. При этом шаблон может храниться как в файле (ключ filename, наиболее частое применение), в скалярной переменной (ключ scalarref, при этом передается ссылка на объект) и в массиве строк (ключ arrayref, также используется ссылка на список). Кроме перечисленных ключей, могут использоваться и дополнительные, которые обеспечивают более точную настройку поведения объекта.

Вот пример создания объекта из шаблона находящегося в файле template.tmpl, при этом задается, что имена шаблонов будут чувствительны к регистру букв:

my $template = HTML::Template->new(filename => 'template.tmpl', case_sensitive => 1);

Если в системе установлена переменная окружения $HTML_TEMPLATE_ROOT, и при шаблон задан относительным именем файла, то к имени будет добавлено значение $HTML_TEMPLATE_ROOT.

Получение результата

Для получения заполненного шаблона просто вызовите функцию output для нужного объекта. При этом возвращается сгенерированный текст. При этом состояние объекта шаблона не меняется.

Поскольку очень часто результат работы записывается в файл, то для того, чтобы уменьшить загрузку, вы с помощью параметра print_to можете передать функции output дескриптор файла, в который будет происходить выдача результатов. Например, вот так:

 $template->output(print_to => *STDOUT);

Вставка переменных

Для вставки данных в шаблон необходимо заполнить его с помощью функции param. Функции param передается хеш данных в виде ключ => значение. Для сложных структур данных, например для вложенных циклов, значением могут быть ссылки на списки и другие хеши. Вот пример простого использования модуля:

use HTML::Template;
# открываем файл с шаблоном
my $template = HTML::Template->new(filename => 'test.tmpl');
# заполняем шаблон параметрами 
$template->param(HOME => $ENV{HOME}, PATH => $ENV{PATH});
# посылаем заголовок Content-Type
print "Content-Type: text/html\n\n";
# выдаем готовый результат
print $template->output;

Для использования в шаблоне переменной с именем VARNAME используется конструкция <TMPL_VAR NAME="VARNAME">. Значение помещенное в хеш с помощью функции param помещается на место данного тэга. При этом у нас получается документ не полностью соответствующий стандарту HTML. Если вы беспокоитесь о правильности синтаксиса вашего документа, то вместо данного тэга можно использовать следующую форму: <!-- TMPL_VAR NAME=PARAM1 -->. Она работает также, как и предыдущая, но не нарушает правильности HTML документа. Обе эти формы можно использовать внутри других тэгов, например так: <IMG SRC="<TMPL_VAR NAME=IMAGE_SRC>">.

Обработка выводимых переменных может контролироваться параметром тэга с именем ESCAPE. Допустимыми значениями являются HTML и URL, при этом происходит преобразование символов, не разрешенных в данном контексте.

Условные операторы

Другой часто используемой конструкцией является условие. Оно имеет форму <TMPL_IF NAME="ИМЯ_УПРАВЛЯЮЩЕГО_ПАРАМЕТРА">Данные 1<TMPL_ELSE>Данные 2</TMPL_IF>. При этом Данные 1 появятся в результате только, если переменная с именем ИМЯ_УПРАВЛЯЮЩЕГО_ПАРАМЕТРА будет иметь истинное значение, в противном случае в результате появятся Данные 2. Модуль допускает использование только одной ветки условия, не используя <TMPL_ELSE>. Заполнение переменной происходит как обычно.

Противоположным по действию тэгу <TMPL_IF..> является тег <TMPL_UNLESS>. Он имеет синтаксис <TMPL_UNLESS NAME="ИМЯ_УПРАВЛЯЮЩЕГО_ПАРАМЕТРА">Данные</TMPL_UNLESS> и вставляет Данные только если переменная ИМЯ_УПРАВЛЯЮЩЕГО_ПАРАМЕТРА имеет ложное значение или вообще не определена.

Функция param может быть использована также для получения значения указанного параметра. Для этого просто вызовите функцию с именем нужного параметра.

Оператор цикла

Важным тэгом является тег, обозначающий цикл. Он имеет следущий синтаксис: <TMPL_LOOP NAME="LOOP_NAME">Повторяющаяся часть</TMPL_LOOP>. Переменная LOOP_NAME должна быть ссылкой на список данных. В этом списке могут хранится и просто значения, и ссылки на другие хеши данных, что позволяет строить вложенные конструкции, как в следующем примере.

Если мы в нашем шаблоне напишем например такую конструкцию

    <table width="100%">
    <TMPL_LOOP NAME=EMPLOYEE_INFO>
        <tr>
          <td>Имя: <TMPL_VAR NAME=NAME></td>
          <td>Должность: <TMPL_VAR NAME=JOB></td>
        </tr>
    </TMPL_LOOP>
    </table>

в скрипте заполним этот шаблон данными:

$template->param(EMPLOYEE_INFO => [{ name => 'Иванов', job => 'программист' },{ name => 'Петров', job => 'менеджер' }]);

то мы получим следующий вывод (только генерируемая часть шаблона):

    <table width="100%">
        <tr>
          <td>Имя: Иванов</td>
          <td>Должность: программист</td>
        </tr>
        <tr>
          <td>Имя: Петров</td>
          <td>Должность: менеджер</td>
        </tr>
    </table>

Важно помнить, что внутри цикла видны только используемые в нем переменные. Для того, чтобы ссылаться на внешние (по отношению к циклу) переменные, вы должны использовать параметр global_vars при создании объекта.

Другие операторы

Модуль также позволяет включать в шаблон другие шаблоны, что помогает использовать повторяющиеся части в разных документах. Для включения файла filename.tmpl используется конструкция <TMPL_INCLUDE NAME="filename.tmpl">. При этом шаблон может включить сам себя и мы получим бесконечную рекурсию. Будьте осторожны! При создании объекта можно указать какая максимальная глубина вложенных файлов может быть достигнута. Это контролируется ключем max_includes.

Заключение

Более подробную информацию о настройках параметров вывода результатов и функциях смотрите справочную страницу HTML::Template.

О других модулях работы с шаблонами мы расскажем в следующих выпусках. Файлы с примерами кода можно скачать в виде ZIP-архива.

 
Автор: Alex Ott
 
Оригинал статьи: http://woweb.ru/publ/58-1-0-356