РАБОТА СО СТАТИЧНЫМ КОНТЕНТОМ СРЕДСТВАМИ WEB-ПРОГРАММИРОВАНИЯ
ЗАЧЕМ ЭТО НУЖНО?
Очень часто мы сталкиваемся с проблемами того, что при незначительном изменении в дизайне или информации сайта (например изменение логотипа или телефона повторяющегося на каждой странице) на "перелопачивание" HTML страниц уходит уйма времени. Конечно проблему решает SSI (Server Side Includes), вынося блоки кода в отдельные файлы, но например так выглядела стартовая страница Пятиком.ру:
<html> <head> <title>Пятиком.ру фирма создание проектов на базе Интернет технологий</title> <meta name="description" content="Создание и ведение крупных проектов в Интернет, поддержка коммерческого сервера, продвижение товаров и услуг Пятигорска"> <meta name="keywords" content="пятиком интернет web дизайн программирование фирма ооо проект ставропольский край пятигорск кавминводы"> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <link rel="StyleSheet" type="text/css" href="http://www.pyaticom.ru/img/style.css"> </head> <body topmargin="0" leftmargin="0" background="http://www.pyaticom.ru/img/bgsmal.gif" rightmargin="0" bottommargin="0" marginheight="0" marginwidth="0"> <!-- Шапка --> <table width="100%" border="0" align="center" cellpadding="0" cellspacing="0"> <!-- Верхняя синяя полоса для служебного --> <!--#include virtual="//linetop.htm"--> <tr> <td height="1" bgcolor="black" colspan="2"></td> </tr> <!-- Логотип и надпись --> <!--#include virtual="//logo.htm"--> <!-- Таблица с банером --> <!--#include virtual="//bantop.htm"--> <tr> <td colspan="3" valign="bottom"> <table width="100%" border="0" cellpadding="0" cellspacing="0" summary=""> <tr> <td height="20" align="left"> <!-- Таблица с верхним меню --> <!--#include virtual="//menutop.htm"--> </td> </tr> <!-- Нижняя полоса шапки --> <!--#include virtual="//submenu.htm"--> </table> </td> </tr> </table> <!-- Основа --> <table width="100%" height="400" border="0" align="center" cellpadding="0" cellspacing="5"> <tr> <!-- Левая часть страницы --> <td width="20%" valign="top"> <!--#include virtual="//informer/menu.htm"--> <!--#include virtual="//informer/left1.htm"--> <!--#include virtual="//informer/left2.htm"--> <!--#include virtual="//informer/left3.htm"--> <!--#include virtual="//informer/left4.htm"--> <!--#include virtual="//informer/left5.htm"--> <!--#include virtual="//informer/left6.htm"--> <!--#include virtual="//informer/left7.htm"--> <!--#include virtual="//informer/left8.htm"--> <!--#include virtual="//informer/left9.htm"--> </td> <!-- Конец Левая часть страницы --> <!-- Центральная часть страницы --> <td width="60%" valign="top"> <!--#include virtual="//cgi-bin/pyaticom/news/news.pl?${QUERY_STRING}"--> </td> <!-- Правая часть страницы --> <td width="20%" valign="top"> <!--#include virtual="//informer/right1.htm"--> <!--#include virtual="//informer/right2.htm"--> <!--#include virtual="//informer/right3.htm"--> <!--#include virtual="//informer/right4.htm"--> <!--#include virtual="//informer/right5.htm"--> <!--#include virtual="//informer/right6.htm"--> <!--#include virtual="//informer/right7.htm"--> <!--#include virtual="//informer/right8.htm"--> <!--#include virtual="//informer/right9.htm"--> </td> </tr> </table> <!-- Нижняя часть --> <table width="100%" border="0" align="center" cellpadding="0" cellspacing="0" summary=""> <tr> <td width="100%" height="20" bgcolor="#134069"></td> </tr> <tr> <td width="100%" height="1" bgcolor="#000000"></td> </tr> <tr> <td width="100%" height="70" bgcolor="#4C709D"> <!-- Таблица для счетчиков банера и копирайта --> <table width="100%" border="0" align="center" cellpadding="0" cellspacing="0" summary=""> <tr> <!--#include virtual="//count.htm"--> <td width="60%"> <!-- Таблица с банером --> <!--#include virtual="//bandown.htm"--> </td> <!-- Копирайт и адрес --> <!--#include virtual="//adress.htm"--> <!-- Конец Копирайт и адрес --> </tr> </table> <!-- Конец Таблица для счетчиков банера и копирайта --> </td> </tr> </table> <!-- Конец Нижняя часть --> </body> </html>
Методом несложных подсчетов выясняем, что только одна стартовая страница состоит как минимум из ДВАДЦАТИ ВОСЬМИ ФАЙЛОВ!!! И это не считая самого index.shtml!!! Да конечно, некоторые файлы, такие как right5.htm или left5.htm были пустыми, так как были написаны на всякий случай… вдруг вздумается добавить еще меню справа или слева. Но все же факт налицо разобраться в такой системе построения таблицы не так-то просто начинающим специалистам. Да и я, хоть и программист, но относительно хорошо ориентирующийся в HTML коде, немного «теряюсь» при виде подобного.
ЦЕЛИ И ЗАДАЧИ:
Нам требуется наиболее упростить процесс работы со статикой и дать возможность начинающим специалистам возможность производить изменения. При возможности сделать оптимизацию HTML кода для его облегчения.
СТРУКТУРА СТРАНИЦ:
Требуется определить из чего же у нас состоит страница? Как правило в разделах сайта - это практически одинаковые страницы, отличающиеся только внутренней частью. То есть страница состоит из 2-х частей шаблон и текст, который мы вставляем в шаблон. У каждого раздела свой шаблон, у каждой страницы свой текст. Так же у нас есть повторяющиеся куски кода (в прошлом информеры) которым мы тоже уделим место: Итак страница у нас будет собирается из таких частей:
- Шаблоны – отдельно для каждого раздела;
- Текстовые части – отдельно для каждой страницы; Блоки – о чем уже говорилось ранее, но они имеют разные виды:
- блок – просто блок кода который мы внедряем в шаблон или текстовую часть;
- информер – блоки кода которые мы внедряем через SSI*;
- Снипеты (snippets) – те же блоки кода, но состоящие из двух частей;
- Изображения – галерея картинок сайта;
- Архивы - файлы zip;
- Стили – собственно CSS;
- Java скрипты – Java скрипты которые применяются на странице;
* Примечание: может показаться, что в использовании SSI отпадает надобность, но это не так, потому как при использовании некоторых скриптов, они создают информеры, для дальнейшего их использования на сайте (например информер последних статей)
СТРУКТУРА СКРИПТА:
Так же требуется определить из каких основных модулей будет состоять наш скрипт, их всего три:
- Создание, изменение и удаление частей страниц;
- Генерация страниц;
- Организация связи между частями страниц;
СХЕМА ФОРМИРОВАНИЯ СТРАНИЦ:
Исходя из вышеизложенного представим схему формирования страницы
РАЗБОР СКРИПТА СТАТИЧНОГО КОНТЕНТА
В первом модуле скрипта мы работаем непосредственно со структурой страниц и их кодом. Соответственно на каждую часть структуры страницы мы заводим свою базу. Изначально я использовал обычные текстовые базы, но скажу, что это немного неудобно так как HTML код страниц категорий блоков и т.д. мне приходилось держать в отдельных файлах и при запросе определенной части я выбирал сначала её из базы а потом в соответствии с полученными параметрами находил и загружал файл с HTML кодом. При использовании баз данных MySQL возможна запись в базу даннх как параметров, так и кода, тем самым сокращается количество запросов. Какие таблицы получаются в базе данных:
- Для: категорий страниц, блоков, стилей и java script:
- id номер (тип поля MEDIUMINT - AUTO_INCREMENT - PRIMARY KEY);
- Название (тип поля VARCHAR до 200 символов - INDEX);
- HTML-код (тип поля TEXT)
- Для страниц:
- id номер (тип поля MEDIUMINT - AUTO_INCREMENT - PRIMARY KEY);
- Название (тип поля VARCHAR до 200 символов - INDEX);
- Имя файла страницы (тип поля VARCHAR до 8 символов, можно конечно использовать в качестве имени файла и id номер, но имена файлов еще должны нести хоть какую-либо смысловую нагрузку для поисковых систем)
- Категория страницы (тип поля MEDIUMINT - является связующим полем с таблицей категорий страниц, для установки принадлежности страницы к определенной категории);
- Заголовок страницы (тип поля VARCHAR до 64 символов - <title>);
- Описание страницы (тип поля VARCHAR до 128 символов - мета тег описания страницы);
- Ключевые слова страницы (тип поля VARCHAR до 255 символов - мета тег ключевых слов страницы);
- HTML-код (тип поля TEXT)
- Для изображений и архивов:
- id номер (тип поля MEDIUMINT - AUTO_INCREMENT - PRIMARY KEY);
- Название (тип поля VARCHAR до 200 символов - INDEX);
- Тип файла - расширение (тип поля VARCHAR до 4 символов);
- Для сниппетов (snippets):
- id номер (тип поля MEDIUMINT - AUTO_INCREMENT - PRIMARY KEY);
- Название (тип поля VARCHAR до 200 символов - INDEX);
- HTML-код "до" (тип поля TEXT)
- HTML-код "после" (тип поля TEXT)
Я использую процедурное программирование поэтому составляем список процедур которые нам необходимы, а так же параметры с помощью которых выбирается определенная процедура. Управляющие параметры следующие:
- mod - непосредственно с чем мы работаем (с какой частью страницы);
- edit - какую операцию мы производим;
- doing - подтверждение операции;
Исходя из вышеперечисленного мы составляем алгоритм нашего скрипта:
Для каждого вывода списка или формы создаем отдельную процедуру, хотя на самом деле большинство процедур выполняет однотипные операции, поэтому оптимизировать скрипт и сократить количество процедур будет очень легко. Все формы однотипные - enctype="text/html", за исключением формы для "создания" изображения или архива, при работе с этими объектами, кроме записи параметров в базу данных, мы производим upload изображения или архива на сервер, поэтому форма имеет тип - enctype="multipart/form-data". Код редактируем через textarea.
Как предполагается указывать связи между всеми частями страниц. Используем свой UBB код:
Второй модуль генерации страниц тоже состоит из определенных процедур, так как полная генерация системы в связи с измением нескольких слов на какой либо странице - бессмысленна. Разберем, при изменении каких частей страницы, что мы будем генерить:
-
При изменении отдельной страницы - генерится только одна страница, но если мы при этом меняем имя файла или название страницы нам прийдется генерировать все страницы;
-
При изменении категории страниц - генерятся все страницы включенные в данную категорию;
-
При изменении блоков кода - нам придется генерировать все страницы, так как у нас нет жесткой привязки блоков к страницам;
-
При изменении информера - генерится только сам информер, ссылка на странице на информер остается неизменной;
-
При изменении стиля - так как я использую подгружаемый стиль, то генерится только один файл style.css;
-
При изменении Java скриптов - они тоже подгружаются (<script type="text/javascript" language="javascript" src="$link"></script>), поэтому генерится только один файл js, который мы редактируем;
- При изменении изображения или архива - может меняться только название, поэтому нужно предусмотреть функцию, которая заменяет это название в кодах страниц:
В соответствии с этим получается такое количество процедур и их описание:
- генерация страниц - три вида:
-
одна страница: При этом процедуре передается дополнительный параметр regen=page, считается, что параметр id - это id номер страницы. Делается выборка из таблицы страниц по фильтру (id страницы = параметр id) и выбираем запись из таблицы категорий соответствующую нашей странице. Производится обработка полученных данных;
-
одна категория: При этом процедуре передается дополнительный параметр regen=category, считается, что параметр id - это id номер категории. Делается выборка из таблицы страниц по фильтру (Категория страницы = параметр id) и выбираем запись из таблицы категорий соответствующую нашей странице. Производится обработка полученных данных;
-
все страницы: При этом процедуре передается только дополнительный параметр regen=all. Сначала выбираем всю таблицу категорий, полученные данные заводим в цикл, в цикле производим выборку данных из таблицы страниц соответствующим текущей категории, полученные данные заводим в еще один цикл и обрабатываем;*
Алгоритм:
-
Генерация информеров - все очень просто: получаем параметр id - id номер информера, подставляем ссылки на страницы, обрабатываем проблемные коды ("подводные камни") и записываем в файл (имя файла - id номер.htm);
-
Генерация Java - так же как и информеры, единственное отличие, ссылки мы не подставляем и расширение файла у нас js;
-
Генерация стилей - немного отличается тем, что файл у нас всего один. Алгоритм простой: выбираем все данные из таблицы стилей запускаем в цикл и записываем в файл в виде:
Имя стиля 1** { код стиля 1} Имя стиля 2 { код стиля 2} Имя стиля 3 { код стиля 3} ...
* - обработку кода мы производим построчно; ** - следует иметь в виду, что имя стиля нельзя писать кириллицей и использовать пробелы;
Третий модуль - организации связей, выплыл у нас сам из вышеизложенного текста, это не что иное как подстановка и замена UBB кода. Здесь вступают в силу наши любимые регулярные выражения. Делаем несколько процедур для каждого вида подстановки (в процедуру мы передаем код строки а возвращаем обработанный код):
Алгоритм подстановки простой (на примере сниппетов):
- Если в строке присутствует выражение: /\[s\:.*\]/ то:
- Выбираем название сниппета: /^.*\[s\:\s*(([A-Яa-яёЁ\w]+)|([A-Яа-яёЁ\w]+[A-Яa-яёЁ\s\w]+[A-Яa-яёЁ\w]+))\s*\].*\[\/s](.*$)|(.*\n$)/$1/;
- Производим выборку данных из таблицы по полученному названию;
- Заменяем код на полученные данные: /\[\/s\]/$snippets_posle/ и /\[s\:[A-Яa-яёЁ\s\w]+\]/$snippets_do/;
Следует заметить, что при обработке блоков после того как мы выбрали данные, нам требуется их тоже обработать на наличие в коде UBB кода;
ЗАКЛЮЧЕНИЕ
Конечно невозможно охватить все тонкости данного решения, но хочу сказать, что решение само по себе довольно простое, но позволяет очень облегчить труд web-мастеров. Сборка сайта порядка 30-40 страниц занимает в общей сложности 6-8 часов. А дальнейшее его изменение и обновление и того меньше. Скрипт (данное решение я реализовал в Perl), по объему не очень большой, все вместе порядка 2500 строк кода, и это без учета того, что я его не оптимизировал. За неделю его нарисовать нет никаких проблем.
Томулевич Сергей (Phoinix) |