|
Если обнаружите в тексте страницы ошибку, выделите ее мышкой и нажмите Ctrl-Enter.
|
|
Perl Templating System
Кратко.
Шаблонизатор Perl Templating System - движок сайта, написанный
на Perl, позволяющий создавать сайты при помощи шаблонов, способных содержать
вставки Perl-кода в HTML. С помощью данного шаблонизатора можно легко выделить
общие части страниц в шаблон, отделить конечные данные от представления и от
кода, а в статичный HTML добавить динамику а-ля PHP, но только на Perl.
Весь этот сайт построен именно на данном движке.
Причины.
Писалось все чисто для себя, поэтому движок ни на что не претендует и не
пытается конкурировать с другими подобными системами. Просто был с одной стороны
некоторый интерес к Web-программированию (отдельное спасибо за идеи
dklab.ru),
а с другой стороны хотелось иметь
инструмент, позволяющий держать общие части страниц сайта в одном месте, чтобы
проще было над сайтом работать. Также хотелось некоторой динамики, но не
через CGI, и тут идея embedded Perl оказалась самой подходящей. Perl был выбран по
той простой причине, что с ним я знаком, и он мне нравится, а с PHP я не знаком,
и знакомиться нет никакого желания.
Следствия.
Получился очень простой, но довольно функциональный и эффективный движок.
Состоит всего из одного файла размером в 2,5 килобайта. Не использует никаких
модулей, разве что Time::HiRes для замера своей скорости, но это фича
необязательная. Помимо подстановки данных в шаблоны занимается выполнением
встроенного в HTML Perl-кода, а также делает всю работу по кэшированию.
Идеология.
Основная эксплуатируемая идея - древовидность сайта. С одной стороны, данные
распределены по дереву каталогов сайта: главная страница в корне,
каталоги-разделы, подкаталоги-подразделы, конечные файлы - конечные данные.
С другой стороны, выдаваемая пользователю HTML-страница тоже представляет
из себя дерево. Причем, чаще всего, соседние листья-страницы в дереве каталогов
для пользователя выглядят очень похоже, имея почти одинаковое оформление
(включая служебные данные, заголовки, шапку, меню..), и различаясь лишь самими
конечными данными. Соответсвенно, логично вынести их общую часть в один файл,
а в него уже в нужном месте включать только конечные данные. Сделать так можно
не только в пределах одного каталога, но и в пределах всего дерева, объединяя
узлы дерева одной глубины. В результате получим самый общий каркас всего сайта
в корне, содержащий самые общие элементы (теги meta, head, body..) и указания,
куда вставить данные разделов. Для каждого раздела тоже будет такой каркас,
описывающий уже не всю страницу, а только ту часть, которая будет вставлена в
каркас (шаблон) более высокого уровня. Шаблон раздела содержит общие для раздела
части и указания, куда вставить данные с более низких уровней и т.д. В конце
дерева лежат уже только конечные данные без оформления.
Основное преимущество
такого представления - каждый элемент сайта описывается только в одном месте.
Чтобы что-то поменять, достаточно изменить это в одном месте, и изменение
отразится на всем поддереве, т.е. на всех страницах, содержащих данный
элемент. Второе преимущество в том, что в отличие от SSI, где обычно
страница-лист включает в себя данные из верхних узлов дерева, и приходится
шапку и подвал хранить в разных файлах, здесь наоборот, верхние узлы включают
в себя данные из нижних. В результате все открывающие и закрывающие тэги всегда
находятся в одном файле, что существенно упрощает верстку.
Причем понятно, что шаблон (каркас) должен уметь включать не один блок (данные
более низкого уровня, или большей глубины), а несколько. Это нужно по меньшей
мере для того, чтобы изменять title при переходе на разные страницы. Поэтому,
каждый файл с данными - как листы (конечные данные), так и промежуточные узлы
(шаблоны) - может содержать не один блок, включаемый шаблонами более высоких
уровней, а несколько блоков.
Спрашивается, а как быть, если какая-то страница, или даже некоторое дерево
страниц, должна выглядеть совсем иначе, нежели это предполагает главный каркас
страницы? Ответ простой: можно сделать независимое поддерево. Т.к. эти страницы
все равно находятся на сайте, то они образуют некоторое поддерево в дереве
каталогов. Достаточно объявить узел, являющийся корневым для данного поддерева,
корнем. Тогда именно он будет считаться каркасом всей страницы, и будут
обрабатываться данные только в пределах этого поддерева. В предельном случае
можно иметь одну-единственную страницу, которая сама себе является корнем.
Как это выглядит.
Все общие части страниц для каждого каталога объединяются в шаблон - файл с
именем default.htpl. В корне сайта лежит главный шаблон - каркас всего сайта.
Он является самым обычным HTML-файлом, у которого в первой строке стоит
специальный комментарий <!--params(root)-->. Это признак корня. Точно
такой же признак можно поставить на любом шаблоне, если нужно сделать
независимое поддерево. После него идет обычный HTML, в котором в тех местах,
где должны быть какие-то блоки с данными, стоят имена этих блоков, заключенные
в знаки "%" (например, %blосkname%). В файлах-шаблонах узлов дерева и в конечных
файлах содержатся именованные блоки. Соответвенно, при обработке шаблона, вместо
%blосkname% будет подставлено содержимое блока с именем blосkname. Определяется
такой блок очень просто:
<!--tеxtblосk(blосkname)-->
Тело блока - HTML-код, который тоже может содержать произвольное число
указаний вставить другие блоки (типа %blосkname2% или %anоthеrthing%).
<!--endblосk-->
Кроме того, любой блок может содержать код на Perl. Делается это способом,
похожим на РНР - код помещается в конструкцию <? ?>:
Here goes our environment:
<pre>
<? foreach $key (keys %ENV) { ?>
$key = $ENV{$key}<br>
<? } ?>
</pre>
Но, в отличие от РНР, чтобы вставить значение переменной, можно просто написать
ее имя прямо в HTML-тексте, никаких конструкций <?= ?> не надо.
Для того, чтобы уметь выделять текущий выбранный раздел в меню, и вообще
реагировать на выбор пользователя, при выполнении кода для каждого шаблона
определена переменная $Chosen, содержащая имя выбранного каталога или файла.
Из соображений эффективности блоки сделаны двух типов - содержащие Perl-код и
не содержащие. Это сделано для того, чтобы не тратить время на трансляцию и
выполнение тех кусков, которые код не содержат. Блок, не содержащий код,
описывается конструкцией <!--tеxtblосk(blосkname)-->, а блок, содержащий
Perl-код, описывается конструкцией <!--pеrlblосk(blосkname)-->.
Заканчиваются они одинаково.
Чтобы превратить исходную HTML-страничку сайта в шаблон или конечный документ,
достаточно расставить в ней эти комментарии - границы блоков. В результате она
остается полноценной HTML-страницей, ее можно редактировать любыми способами.
После всех редакций можно убрать из нее все, что находится за пределами блоков,
- теперь это уже лишняя информация. Тэг title считается блоком с именем title.
Т.е. чтобы описать блок title не нужно городить огород из конструкций начала
и конца блока, нужно просто оставить как был исходный тэг.
В первой строке файла могут быть указаны его параметры. Они описываются
конструкцией <!--params()-->, где в скобках могут быть
указаны следующие ключи:
nocache - данный узел и все поддерево под ним не кэшируется
root - данный шаблон является корневым
perl - используется там, где указан root. Означает, что корневой шаблон
содержит код на Perl Примеры:
<!--params(root perl)-->
<!--params(perl, root)-->
<!--params(nocache)-->
Строка с параметрами "съедается" движком и пользователю не выводится. Поэтому
она не мешает иметь в первой строке страницы тэг DOCTYPE.
Как это работает.
При запросе какого-то конечного HTML-документа (адреса всех страниц остаются
как были) управление передается шаблонизатору. Он читает запрашиваемый файл
и разбирает его на блоки. Блоки, содержащие код, выполняются, превращаясь в
текстовые (уже с результатами работы). Затем происходит подстановка блоков в
конструкции %% (т.е. можно вставлять блоки, описанные даже в этом же файле).
Потом шаблонизатор находит шаблон default.htpl в том же каталоге, где находится
запрашиваемый документ. Также разбирает на блоки, выполняет, подставляет.
Потом находит шаблон в каталоге уровнем выше. Опять разбирает на блоки,
выполняет, подставляет. И так в цикле до тех пор, пока не наткнется на шаблон с
пометкой root. Он уже не содержит блоков, т.к. является одним большим блоком -
корневым. Он выполняется (если надо) и происходит подстановка. В результате
получается итоговая страница, которая и выдается пользователю.
Уже после выдачи
пользователю она записывается в кэш, при условии, что ни в одном из файлов
обработанной цепочки не было параметра nocache. При следующем запросе этого
документа, при наличии его в кэше, шаблонизатор сначала сравнивает дату файла
в кэше с датами всех файлов цепочки (т.е. конечных данных и шаблонов), и если
кэшированный файл создан позже, то он сразу выдается пользователю. Т.е. все
ограничивается чтением одного-единственного файла, никакой обработки.
Как это установить.
Достаточно поместить файл-движок в каталог, где лежат все CGI-скрипты, а
в корень сайта в .htaccess прописать его в качестве обработчика HTML-файлов.
Кроме этого, надо в корне сайта создать каталог с именем cache.
Скачать архив с шаблонизатором и сайтом-примером (3 кб).
Вопросы.
-Можно ли тут обрабатывать GET и POST запросы?
-Да, если документ содержит блоки с кодом, и к этому документу обращаются с
запросом, то код чувствует себя как обычный CGI - в переменных окружения есть
вся необходимая информация.
-А где же обещанное отделение кода от данных?
-Предлагается выносить весь код (обрабатывающий данные, но сам ничего не
выводящий, а сохраняющий результат в переменные) в отдельные файлы, а в
шаблоне делать <? do "code.pl"; ?>, после чего просто ставить в шаблоне
имена переменных с результатами. Да, это придется делать вручную, но все равно
это лучше, чем выводить HTML из CGI-скрипта.
|