Автор: Phoinix (Томулевич Сергей)
Источник: www.asit.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 |
Товар 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-мастеров.