Использование шаблонов при программировании web-приложений в среде Perl
Зачем вообще использовать шаблоны?
Может, кто-то скажет, а
зачем выносить HTML код в отдельный файл если его можно
спокойно писать в скрипте? Да конечно в скрипте можно писать
HTML код, но просмотреть полностью <собранную>, или частично
<собранную> страницу которую выводит скрипт, возможно только
при его нормальной работе, а во время отладки скрипта, как
правило, возникают некоторые трудности. Потом при смене
дизайна, опять же, править HTML код в скрипте сущая каторга,
сколько раз я слышал о нареканиях со стороны Web-мастеров, что
понять какие куски кода и в какой последовательности выносятся
невозможно, так как, по большей части, они не программисты и
вникать в код скрипта не намерены. И так далее и тому
подобное, поэтому, все-таки будем разделять скрипты от HTML
кода:
Какая должна быть структура шаблонов
Сначала, вынося HTML код из
скриптов, я каждый кусок записывал в отдельный файл. Да когда
нет особых сложностей в сборке страницы (шапка, основа,
подвал), то трудностей нет, но когда страница имеет сложные
внедрения, такие как списки, причем одновременно разных видов
(например список страниц и список товаров текущей страницы),
количество файлов начинало возрастать с неимоверной быстротой
(у меня дошло до того, что страница стала собираться из 28
файлов!!!), и опять возникли трудности, неимоверное количество
кусков кода, настолько усложнило их обработку и
редактирование, что я пришел опять к изначальной
точке: Потом пришла идея - использовать в
качестве шаблона, всего 1 файл, который легко редактировать и
который легко предварительно просмотреть визуально. То есть
использовать в качестве шаблона уже практически готовую
страницу, а разбивать её на куски будет сам скрипт.
Пример вывода страницы списка товаров с использованием одного шаблона
<html> <head> <title>Шаблон
списка товаров</title> <meta
http-equiv="Content-Type"
content="text/html;
charset=windows-1251"> </head> <body> <table width="100%" border="0"> <tr> <td> Список
товаров категории
1 </td> </tr> <tr> <td> Страницы
<
<font color="red"><b>1</b></font> <a href="?category=1&page=1">2</a> <a href="?category=1&page=1">3</a> <a href="?category=1&page=1">4</a> > </td> </tr> <tr> <td> <table
width="98%" border="0"
> <tr> <td>№
п.п.</td> <td>Наименование
товара</td> <td>Цена
товара</td> </tr> <tr> <td>1</td> <td>Товар
№ 1</td> <td>100
р.</td> </tr> <tr> <td>2</td> <td>Товар
№ 2</td> <td>150
р.</td> </tr> <tr> <td>3</td> <td>Товар
№ 3</td> <td>200
р.</td> </tr> </table> </td> </tr> <tr> <td> Страницы
< <font
color="red"><b>1</b></font> <a
href="?category=1&page=1">2</a> <a
href="?category=1&page=1">3</a> <a
href="?category=1&page=1">4</a> > </td> </tr> </table> </body> </html>
Выглядит наша таблица как:
Список товаров категории 1 |
Страницы < 1 2 3 4
> |
№ п.п. |
Наименование товара |
Цена товара |
1 |
Товар 1 |
100 р. |
2 |
Товар 2 |
150 р. |
3 |
Товар 3 |
200 р. | |
Страницы < 1 2 3 4
> |
Какие блоки кода нам понадобятся:
- Страницы, причем вся строка, так как в зависимости от
того, сколько у нас будет товаров, у нас будет либо
постраничный вывод, либо все товары уместятся на одной
странице. Отдельно из этой строки нам понадобится текущая
страница, и ссылка на другую страницу;
- Строка с выводом товара;
Что нужно будет изменять на странице:
- Заголовок страницы;
- Заголовок таблицы (название категории);
- Количество и номера страниц;
- № п.п., Наименование товара и Цена товара
После обработки получаем такой HTML-код:
<html> <head> <title>Список
товаров категории %name_category%, страница %n_page%</title> <meta
http-equiv="Content-Type"
content="text/html;
charset=windows-1251"> </head> <body> <table width="100%" border="0"
> <tr> <td> Список
товаров категории %name_category% </td> </tr> <tr> <td> Страницы < <font color="red"><b>%n_page%</b></font> <a
href="?category=%id_category%&page=%n_page%">%n_page%</a>
> </td> </tr>
<tr> <td> <table
width="98%" border="0"
> <tr> <td>№
п.п.</td> <td>Наименование
товара</td> <td>Цена
товара</td> </tr> <tr> <td> %npp% </td> <td> %name_goods% </td> <td> %price_goods% </td> </tr>
</table> </td> </tr>
</table> </body> </html>
Что получается? Перед каждой строкой определенного блока
кода мы вставили небольшой комментарий в виде , и в тех местах, где мы
должны вставить код мы добавили по дополнительному комментарию
(, , ). Причем комментарий
у нас получился в
середине куска кода который мы отметили как ! Почему мы использовали
именно комментарии? Да потому, что при просмотре этого шаблона
мы увидим все как положено, без лишних вещей:
Список товаров категории
%name_category% |
Страницы < %n_page% %n_page%
> |
№ п.п. |
Наименование товара |
Цена товара |
%npp% |
%name_goods% |
%price_goods% | |
Мы можем проверить стили и
общий дизайн <не отходя от кассы>. Почему мы поставили
комментарии напротив каждой строки, а не, скажем, просто метки
начала и конца блока? Да потому, что в случае вывода строки
списка номеров страниц, нам требуется <выкусить> часть блока,
а потом, после обработки, вставить обратно, нам бы пришлось
этот блок разбивать не на 3 части а на 4 (начало блока,
текущая страница, ссылка на другую страницу, конец блока). Да
и потом, мне лично визуально гораздо проще видеть эти блоки в
коде.
Ну теперь когда мы сделали шаблон, попробуем его
обработать:
У нас есть переменная $category - название
категории; У нас есть переменная $id_category -
идентификатор категории; У нас есть переменная
$num_goods - количество товаров на странице; У нас
есть переменная $on_page - текущая страница; У нас
есть массив @goods - наши товары в виде -
Наименование|цена|
Пишем код:
# Загружаем шаблон
$file = "list.html"; open (TMP, "$file"); @template
= ; close ($file);
# Разрезаем его на
блоки:
foreach (@template) { if (m//)
{ $_
=~s ///g; #Избавляемся
от ненужного
комментария @line_pages
= (@line_pages, $_); #Собираем
блок $_
= ""; #Обнуляем
строку
шаблона } if (m//)
{ $_
=~s ///g; #Избавляемся
от ненужного
комментария @on_page
= (@on_page, $_); #Собираем
блок* $_
= ""; #Обнуляем строку
шаблона } if (m//)
{ $_
=~s ///g; #Избавляемся от ненужного
комментария @off_page
= (@off_page, $_); #Собираем
блок* $_
= ""; #Обнуляем строку
шаблона } if (m//)
{ $_
=~s ///g; #Избавляемся
от ненужного
комментария @line_goods
= (@line_goods, $_); #Собираем
блок $_
= ""; #Обнуляем строку
шаблона } }
* Примечание: Почему мы забираем всего 1
строку в массив? да на всякий случай, вдруг завтра это
выражение мы будем писать несколькими строчками в HTML
коде.
# Собираем строку с номерами
страниц
$number = @goods; # Если
количество товаров меньше или равно количеству товаров
выводимых # на странице, то обнуляем блок где выводится
список номеров страниц if ($number <= $number_page) {@line_pages = ();} else { $number_page
=
$number/$num_goods; for ($i = 0; $i < $number_page;
$i++)
{ $page
= $i + 1; # Проверяем текущую
страницу, и в зависимости от этого присваиваем #
временному массиву соответствующий блок if
($page eq $on_page) {@temp_line = @on_page;} else
{@temp_line =
@off_page;} # Обрабатываем текущий
массив
foreach (@temp_line) {
$_ =~s
/%id_category%/$id_category/gi;
$_ =~s
/%n_page%/$page/gi;
} # Прибавляем полученный массив к списку номеров
старниц
@temp_list
= (@temp_list,
@temp_line);
} # Обрабатываем блок с линией списка номеров
страниц* foreach (@line_pages) { $_ =~s //@temp_list/gi; } }
* Примечание: Подобную процедуру можно
производить и в конце во время окончательной обработки
шаблона.
# Собираем таблицу с
товарами
$first_goods = ($page - 1)*$num_goods; $last_goods =
($page)*$num_goods; if
($last_goods > $number) {$last_goods = $number;}
for ($i = $first_goods;
$i < $last_goods; $i++) { ($name, $price) =
split(/|/,@goods[$i]); # присваиваем
временному массиву соответствующий блок
@temp_line =
@line_goods; $npp = $i + 1; foreach
(@temp_line) { $_ =~s
/%npp%/$npp/gi; $_ =~s
/%name_goods%/$name/gi; $_ =~s
/%price_goods%/$price/gi; } # Прибавляем полученный массив к таблице
товаров @list_goods = (@list_goods,
@temp_line); }
# Окончательная обработка
шаблона
foreach (@template) { $_ =~s
//@list_goods/gi;
$_ =~s //@line_pages/gi; # $_ =~s
//@temp_list/gi;* }
* Примечание: Если мы подобную процедуру не
произвели ранее
# Выводим результат на экран
print "Content-type: text/html; charset=windows-1251
"; print "@template"; exit;
Заключение
Конечно использование данного метода может немного
замедлить работу скрипта, так как проводится довольно много
циклов, но убрав HTML-код из скрипта мы, тем самым, уменьшили
его размер, а собрав шаблон в один файл, мы упростили
дальнейшую работу с ним.
Так же подобное решение использовано на сайте Пятиком.ру и
других смежных проектах в динамичных разделах и административном интерфейсе, и пока не
вызывало нареканий со стороны web-мастеров.
Автор: Phoinix (Томулевич Сергей)
Источник: www.asit.ru
|