HTML-шаблоны для PHP и Perl, или Не делайте инструмент самоцелью!
Архив номеров / 2004 / Выпуск №8 (21) / HTML-шаблоны для PHP и Perl, или Не делайте инструмент самоцелью!
ДМИТРИЙ ГОРЯИНОВ
HTML-шаблоны для PHP и Perl, или не делайте инструмент самоцелью!
О шаблонах в веб-программировании знают или слышали буквально все. Интерпретируемые языки веб-программирования, такие как PHP, Perl, ASP VBScript, всегда давали возможность совмещать код языка и HTML. Это быстро и просто. Вначале. Как только проект или отдельный файл-сценарий начинают разрастаться, эта смесь так же быстро становится неудобоваримой. Взявшись переписывать какой-либо сценарий, сразу хочется выкинуть HTML-вставки просто потому, что они начинают мешать читать программный код.
Ради этого, ради разделения HTML-форматирования вывода и логики программы и был придуман механизм шаблонов. Логика остается программе, верстка – шаблону.
Программа обрабатывает запрос, формирует данные и заполняет шаблон. Шаблон всегда содержит HTML-код и некоторые дополнительные конструкции для вставки данных и управления выводом. Тут необходимо кое-что прояснить.
Небольшой взгляд в историю, или Каким должен быть шаблонный движок?
Несомненно, идея шаблонов пришла в голову программистам. И суть идеи явно была в том, чтобы убрать HTML-код из программы. А вот дальше… Дальше все складывалось по-разному. Понятно, что первыми «родились» простейшие шаблоны. Это просто HTML-код и специальные указания для вставки данных. По сути, переменные.
Такой простой HTML-документ. Можно сохранить и открыть в браузере. Будет страничка с заголовком «::title::» и содержимым «::body::».
Есть конструкция (::имя::), которую нужно выделить из HTML-кода, есть некоторое имя, вместо которого нужно подставить данные из программы. Можете называть это переменной, но лучше назовем это именованной вставкой.
Дальше все стало гораздо более запутанно. Довольно быстро выяснилось, что есть блоки, которые могут повторяться на одной и той же странице. А иногда на этой странице в зависимости от некоторого условия нужно либо выводить что-то, либо нет.
Вот тут началось жуткое многообразие. В шаблоны стали добавлять макроязыки. При этом, в зависимости от квалификации авторов системы, в шаблоны внедряли условные операторы, операторы циклов, регулярные выражения, макрофункции и даже объекты (последним сильно грешат системы шаблонов для языка Java). К чему же это привело?
Кроме того, что авторы систем поупражнялись в написании мини-трансляторов, это привело к тому, что человек, хорошо владеющий навыками HTML-верстки, не мог создать ни один более-менее полезный шаблон.
Он должен был предварительно изучить новый для себя синтаксис.
И при этом все, что нам действительно нужно от шаблона это:
- возможность указать место для вставки данных;
- выделить блок HTML-кода, который можно будет включить или не включить в конечный вывод или, допустим, повторить нужное количество раз.
В идеале синтаксис дополнительных конструкций должен позволять работать с шаблоном в традиционном HTML-редакторе и просматривать готовый файл-шаблон в браузере.
Систем шаблонов написано действительно много. Мы будем рассматривать две из них (одну для языка PHP и вторую – для Perl). Основная цель статьи – показать, как правильно работать с готовыми движками, чтобы минимизировать изменения в HTML-коде шаблонов и оставить логику за программой.
Добавление шаблонного движка в проект
Итак, что вообще требуется от шаблонного движка? Как минимум – установить, подключить и начать использовать.
Во-первых, основная цель проекта не в том, чтобы поработать с шаблонами. Наша система будет загружена собственной полезной работой, и тратить большие ресурсы на поддержание работы с шаблонами крайне нежелательно. Во-вторых, нам вряд ли подойдет движок, который потребует дополнительной компиляции каких-либо компонент или изменения конфигурации веб-сервера. Дело даже не в том, что у нас нет своего сервера, а злой дядька провайдер не желает что-то там собрать-подключить на своей площадке. Просто вариант «отдельный проект – отдельный сервер» почти нереален. Скорее всего, наш сервер уже обслуживает какие-то проекты и нет ни малейшего желания бросаться их переписывать на новый лад или менять рабочую конфигурацию. Да и останавливать боевой сервер ради добавления «новой забавы» мало кто (читай – системный администратор) согласится.
Поэтому лучше всего нам подойдет движок, который можно скачать, разархивировать и начать использовать без всякой дополнительной инсталляции.
В качестве движка для PHP мы рассмотрим библиотеку XTemplate (http://sourceforge.net/projects/xtpl), а для Perl – модуль HTML::Template (http://html-template.sourceforge.net). Оба движка достаточно именно скачать и разархивировать. Вы, конечно, можете установить модуль для Perl по всем правилам, но вполне достаточно развернуть из архива каталог HTML с файлом-модулем Template.pm в нем.
Куда разархивировать? Для простоты предлагается создать отдельный каталог для дополнительных библиотек. Пусть каталог htdocs – это корневой каталог размещения документов на веб-сервере. Создадим на одном уровне с ним каталог lib, и разархивируем в него наши движки, каждый – в отдельный каталог. Получится вот такая структура директорий:
В каталоге XTemplate будут файлы PHP-библиотеки, демонстрационные примеры и т. п. В каталоге HTML может находиться один-единственный perl-модуль – Template.pm
Собственно, на этом все необходимые манипуляции по установке будут закончены. Просто и эффективно, не правда ли?
Просто отдельный класс
Итак, мы решили отказаться от движков, требующих специальной инсталляции. Установка наших библиотек сводится к разархивированию или простому копированию. Пойдем дальше.
Движок должен быть инкапсулирован в отдельный класс. Он не должен иметь ветвистых зависимостей с другими модулями. Иначе устанешь их удовлетворять.
Множество хороших веб-программистов создавали и будут создавать свои, уникальные решения в рамках отдельных проектов. В таких случаях что-то непременно «затачивается» под конкретные нужды, что-то «дергается напрямую» и т. д. На базе таких решений вырастают системы публикаций или управления сайтами. Все это плотно упаковано, скручено в тугой узел, плохо отделимо друг от друга и, возможно, представляет собой законченный продукт, который, скорее всего, больше никому, кроме заказчика, не пригодится.
Если же речь идет именно о подсистеме для работы с шаблонами, то такая система должна представлять собой законченный интерфейс, отделимый от остальной системы. Фактически – уникальный класс либо модуль.
Программист, использующий движок, не должен тратить время на попытку понять, как оно должно было работать в соответствии с замыслом автора модуля или выполнять с десяток настроек. Нам нужен инструмент для работы, а не инструкция по обработке паровоза напильником с целью получить истребитель.
В нашем случае это требование выполняется полностью. Нам нужно просто подключить новую библиотеку, согласуясь с синтаксисом языка.
Библиотеку PHP XTemplate мы разместили в подкаталоге XTemplate каталога lib. Класс XTemplate содержится в файле xtpl.p.
Для того чтобы создать новый экземпляр класса, нам нужно подключить файл и создать объект:
$xtpl=new XTemplate( полное_имя_файла_шаблона );
Для подключения библиотеки HTML::Template в Perl следует указать путь к её директории (если, как в нашем случае, она размещена отдельно от стандартных библиотек), подключить модуль и так же создать новый объект:
# Другой способ добавить каталог размещения библиотеки:
my $template = HTML::Template->new( filename => полное_имя_файла_шаблона );
Что же такое шаблон?
Вернемся к началу. Для чего затевалась вся эта история с шаблонами? В основном для того, чтобы отделить код HTML от кода программы. Идеальный шаблон – это файл, содержащий HTML-разметку, и программно заполняемый данными.
Одно из направлений в системах шаблонов – предварительная компиляция шаблонов в некоторое внутреннее представление. Обычно это убыстряет вывод программы, но любое изменение в шаблоне требует как минимум перекомпилирования его самого и, возможно, несколько зависимых шаблонов.
То есть никакое изменение в HTML-коде не может сразу отразиться на сайте. Пока такие системы не дают настолько ощутимого выигрыша в скорости, чтобы считать это действительно хорошим решением.
Так что сформулируем еще один постулат – движок не должен требовать дополнительной обработки шаблонов (читай – запретить предварительную компиляцию и прочие действия).
Шаблон должен редактироваться как HTML-файл, иметь возможность предварительного просмотра как HTML-файл и подключаться «как есть». Мы же не хотим заставить верстальщика установить у себя веб-сервер лишь для того, чтобы просматривать промежуточные результаты своей работы?
Вот два простых примера шаблонов для XTemplate и HTML::Template.
Пример шаблона для библиотеки Xtemplate:
<dt>Значения переменных добавляются в XTemplate через метод
Если мы сохраним этот код в файле ex1.html и откроем его для просмотра в браузере, мы увидим такую «картинку»:
Рисунок 1. Вид шаблона для XTemplate в браузере
Пример шаблона для библиотеки HTML::Template:
<dt>Значения переменных добавляются в HTML::Template через метод
Так как подстановки в шаблонах HTML::Template имеют синтаксис, схожий с HTML-тэгами, HTML-вид шаблона будет слегка отличаться:
Рисунок 2. Вид шаблона для HTML::Template в браузере
Код подстановки () не отобразится в браузере. Фактически браузер воспримет этот как HTML-тэг, правило отображения которого ему неизвестно.
Лучшее – враг хорошего. Минимизируем логику, макроязык шаблонов
Теперь постараемся разобраться с тем, что нам действительно понадобится в шаблонах, кроме HTML-кода.
Есть несколько типичных задач, с которыми мы сталкиваемся постоянно и для которых мы хотим иметь четкое и простое решение. Хорошим примером такой задачи может служить вывод таблицы с чередованием фона строк. При выводе таблицы мы, во-первых, имеем дело с повторяющимися элементами (строками), во-вторых, чередование цвета фона – это выбор оформления в зависимости от условия.
Шаблон «ex2.html» для библиотеки Xtemplate:
<table bgcolor="gray" cellspacing=2 border=0 cellpadding=4>
Рассмотрим шаблон подробнее. Прежде всего отметим, что весь шаблон для XTemplate заключен внутри именованного блока:
Это необходимое условие синтаксиса шаблонов XTemplate. Любой блок (и весь шаблон целиком) начинается с конструкции:
И заканчивается конструкцией:
Простая подстановка в шаблоне описывается так:
Там, где логика подсказывает нам сгруппировать данные для подстановки, можно использовать массивы подстановок, описывая их таким образом:
К примеру, это логично сделать при оформлении подстановок значений ячеек табличной строки.
Шаблон описывает HTML-код для вывода данных. Сами данные формируются в программе. На уровне шаблона мы не можем предусмотреть количество элементов нашей таблицы.
Поэтому каждую строку таблицы мы оформим в шаблоне в виде отдельного блока. Это делается для того, чтобы иметь возможность управлять выводом отдельных строк из программы-обработчика:
Внутри блока item мы опишем два других блока – «odd» и «even» – для чередования оформления строк. Программа-обработчик, проверяя условие четности строки, будет выбирать нужный блок и управлять генерацией конечного HTML-вывода, формируя содержимое блока item.
В XTemplate вся логика организации циклов и условий ложится на код PHP-программы. В шаблоне описываются только блоки и имена для подстановки значений.
Опишем PHP-код, обрабатывающий этот шаблон:
include( getenv("DOCUMENT_ROOT") ."/../lib/XTemplate/xtpl.p" );
// Создание нового объекта. файл шаблона ex2.html
// размещаем в каталоге htdocs/../data/xtemp
$xtpl=new XTemplate( getenv("DOCUMENT_ROOT") ."/../data/xtemp/ex2.html" );
// Простая подстановка значения в
$xtpl->assign( TOPIC, "Вывод таблицы с чередованием фона строк" );
// Цикл для формирования строк таблицы
// В зависимости от четности строки указываем
// блок-шаблон вывода «odd» или «even»
if ( ($even = ($even XOR 1)) )