Использование шаблонов при программировании WEB-приложений
www.webscript.ru
Зачем вообще использовать шаблоны?
Может, кто-то скажет, а зачем выносить 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 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> <!-- 1 --> <tr> <!-- 1 --> <td> <!-- 1 --> Страницы < <!-- 2 --> <font color="red"><b>%n_page%</b></font> <!-- 3 --> <a href="?category=%id_category%&page=%n_page%">%n_page%</a> <!-- 1 --> <!-- pages --> <!-- 1 --> > <!-- 1 --> </td> <!-- 1 --> </tr> <!-- list_pages --> <tr> <td> <table width="98%" border="0" > <tr> <td>№ п.п.</td> <td>Наименование товара</td> <td>Цена товара</td> </tr> <!-- 4 --> <tr> <!-- 4 --> <td> <!-- 4 --> %npp% <!-- 4 --> </td> <!-- 4 --> <td> <!-- 4 --> %name_goods% <!-- 4 --> </td> <!-- 4 --> <td> <!-- 4 --> %price_goods% <!-- 4 --> </td> <!-- 4 --> </tr> <!-- list_goods --> </table> </td> </tr> <!-- list_pages --> </table> </body> </html>
Что получается? Перед каждой строкой определенного блока кода мы вставили небольшой комментарий в виде <!-- цифра -->, и в тех местах, где мы должны вставить код мы добавили по дополнительному комментарию (<!--pages -->, <!-- list_pages -->, <!-- list_goods -->). Причем комментарий <!--pages --> у нас получился в середине куска кода который мы отметили как <!-- 1 -->!
Почему мы использовали именно комментарии? Да потому, что при просмотре этого шаблона мы увидим все как положено, без лишних вещей:
Список товаров категории %name_category% | ||||||
Страницы < %n_page% %n_page% > | ||||||
|
Мы можем проверить стили и общий дизайн <не отходя от кассы>.
Почему мы поставили комментарии напротив каждой строки, а не, скажем, просто метки начала и конца блока? Да потому, что в случае вывода строки списка номеров страниц, нам требуется <выкусить> часть блока, а потом, после обработки, вставить обратно, нам бы пришлось этот блок разбивать не на 3 части а на 4 (начало блока, текущая страница, ссылка на другую страницу, конец блока). Да и потом, мне лично визуально гораздо проще видеть эти блоки в коде.
Ну теперь когда мы сделали шаблон, попробуем его обработать:
- У нас есть переменная $category - название категории;
- У нас есть переменная $id_category - идентификатор категории;
- У нас есть переменная $num_goods - количество товаров на странице;
- У нас есть переменная $on_page - текущая страница;
- У нас есть массив @goods - наши товары в виде - Наименование|цена|
Пишем код:
# Загружаем шаблон $file = "list.html"; open (TMP, "$file"); @template = <TMP>; close ($file); # Разрезаем его на блоки: foreach (@template) { if (m/<!-- 1 -->/) { #Избавляемся от ненужного комментария $_ =~s /<!-- 1 -->//g; #Собираем блок @line_pages = (@line_pages, $_); #Обнуляем строку шаблона $_ = ""; } if (m/<!-- 2 -->/) { #Избавляемся от ненужного комментария $_ =~s /<!-- 2 -->//g; #Собираем блок* @on_page = (@on_page, $_); #Обнуляем строку шаблона $_ = ""; } if (m/<!-- 3 -->/) { #Избавляемся от ненужного комментария $_ =~s /<!-- 3 -->//g; #Собираем блок* @off_page = (@off_page, $_); #Обнуляем строку шаблона $_ = ""; } if (m/<!-- 3 -->/) { #Избавляемся от ненужного комментария $_ =~s /<!-- 3 -->//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 /<!-- pages -->/@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 -->/@list_goods/gi; $_ =~s /<!-- list_pages -->/@line_pages/gi; # $_ =~s /<!-- pages -->/@temp_list/gi;* } * Примечание: Если мы подобную процедуру не произвели ранее # Выводим результат на экран print "Content-type: text/html; charset=windows-1251\n\n"; print "@template"; exit;
Заключение
Конечно использование данного метода может немного замедлить работу скрипта, так как проводится довольно много циклов, но убрав HTML-код из скрипта мы, тем самым, уменьшили его размер, а собрав шаблон в один файл, мы упростили дальнейшую работу с ним.
Так же подобное решение использовано на сайте Пятиком.ру ( http://www.pyaticom.ru ) и других смежных проектах в динамичных разделах ( http://www.pyaticom.ru/news.shtml?category=centr_up ) и административном интерфейсе ( http://web.pyaticom.ru/news_l.shtml ), и пока не вызывало нареканий со стороны web-мастеров.
Оставить комментарий
Комментарии
test.php
..............................
..............................
$tp_title="Пример использования шаблона";
$tp_s1="Пример использования шаблона";
..............................
..............................
..............................
include "1.tp";
?>
1.tp
echo "
<HTML>
<HEAD>
<TITLE>$tp_title</TITLE>
</HEAD>
<BODY>
<B>$tp_s1</B>
</BODY>
</HTML>
"; ?>
И работает быстро.
line 7 - это: @template = <TMP>;
..ничего не понимаю...помогите!