Сделай Сам Свою Работу на 5

Тема 10. Шаблоны в PHP. Взаимодействие PHP и MySQL





 

Шаблоны в PHP

 

Разделение оформления и содержания – извечная проблема веб-разработчика. Для держателя небольшого сайта в несколько страниц такой проблемы не возникает и изменение дизайна, либо другая правка внешнего вида страниц для него не представляет трудностей. Однако для крупных веб-ресурсов и порталов смешение этих двух важнейших компонентов сайта – оформления и содержания – просто недопустимо. Иначе сайт становится настолько неповоротлив, что владелец ресурса теряет над ним управление.

Столкнувшись однажды с такой проблемой, сайтостроители начали ломать голову над тем, как сделать так, чтобы информация не привязывалась никоем образом к дизайну и наоборот, чтобы внешний вид всего сайта менялся буквально одним движением руки.

Необходимо сказать, что способа идеального разделения оформления и содержания в наши дни пока не найдено. Но все же созданы определенные наработки и технологии, которые позволяют максимально приблизиться к этому идеалу. Прежде всего это технология использования шаблонов.

Понятие "шаблон" довольно обширно. Но чаще всего под шаблоном понимается некий документ (обычно в формате HTML), содержащий в себе всё оформление ресурса, либо только его части, а также специальные метки, которые в процессе генерации страницы заменяются на информационные данные.



Для работы с шаблонами используются специальные веб-приложения (если говорить о веб-разработках), которые могут обладать различными свойствами и функциями. Но чаще всего их роль сводится к тому, чтобы заменять вышеуказанные метки на информационные блоки и соединять полученные части страниц в единое целое.

Наверное, во всех языках вебпрограммирования есть подобные инструменты для работы с шаблонами: в Perl это FastTemplate (который, кстати, существует и для PHP, но его использование не рекомендуется, так как приемлемые для работы версии относятся еще к третьей версии PHP), в отношении PHP – это крупный и многофункциональный Smarty, а также ряд других более мелких "шаблонизаторов".

Smarty – одна из самых крупных разработок подобного рода. Реализован он, как и практически все приложения подобного типа, в виде класса.



Этот "шаблонизатор" имеет огромное количество возможностей: он не только осуществляет замену выделенных участков шаблона указанными данными, но и предоставляет использование внутри шаблона исполняемых участков, функций, конфигурационных файлов и т.д.

Описывать все его возможности и правила использвования не имеет смысла из-за экономии времени, к тому же к нему написана довольно хорошая документация, а примеры использования прилагаются к самому Smarty.

Smarty – это настоящий монстр по работе с шаблонами. Но, как понимаете, за столь широкую функциональность приходится платить ресурсами сервера и временем исполнения скрипта на его основе. В некоторых случаях из-за своей громоздкости Smarty кажется неповоротливым. Поэтому для сравнительно небольших проектов использование Smarty – обычно далеко не лучший выбор. В этом случае следует обратить внимание на более мелкие и менее функциональные, но тем не менее достойные инструменты.

Рассмотрим более простой пример шаблонов.

Код шаблона помещается внутрь HTML страницы и занимается генерацией динамического содержимого.

Пример 10.1.1:

 

<HTML>

<head>

<title>Простейшая страничка</title>

<head>

<body>

<!-- Здесь меню сайта -->

<table width="100%" border="0" cellspacing="0" cellpadding="1">

<tr>

<td><a href="page1.php">Страница 1</a></td>

<td><a href="page2.php">Страница 2</a></td>

<td><a href="page3.php">Страница 3</a></td>

</tr>

</table>

<!-- Непосредственно содержимое страницы, генерируемое PHP -->

<?php echo '<p>Динамический content страницы</p>'; ?>



<!-- Footer страницы -->

<p>(с) 2001 Вася Пупкин</p>

</body>

</HTML>

 

На первый взгляд это очень удобно. И это действительно удобно, но как правило только в случае, если страница несложная и динамического кода в ней немного. А теперь посмотрите на современные сайты в интернете – на каждой странице собрано множество разнообразной информации, причём, как правило, эта информация представляет собой различную функциональность: например, меню сайта, последние новости, голосование, поиск, ссылки, реклама и т.п. – и всё это на одной странице. Да и струртура HTML кода подобной страницы довольно сложна. Я думаю, что вы понимаете, что использование метода "встраивания" PHP кода в подобную страницу ничего кроме головной боли и кучи трудноуловимых глюков вам не принесёт. Более того, web-программисты (да и не только они) повсеместно стремятся как можно сильнее отделить код сайта от его визуальной части, чтобы не приходилось переписывать код при каждом изменении внешнего вида сайта. Вот здесь-то и возникает идея использования шаблонов как средства разделения внешнего вида и внутреннего кода сайта.

Итак, шаблоны – это механизм, который позволит вам в большей или меньшей степени избавиться от тесной привязки вашего кода к внешнему виду вашего сайта и поможет вам облегчить задачу генерации динамического HTML кода страниц. Основная идея этого механизма состоит в том, чтобы иметь множество "кусочков" HTML кода из которых вы потом, как из кубиков в конструкторе, соберете любую страницу вашего сайта.

Простейший способ использования шаблонов – это создание множества переменных, содержащих кусочки HTML кода. Код самой страницы при этом самостоятельно занимается объединением HTML кода из этих переменных с необходимыми данными для получения результата. Посмотрим, например, как могла бы выглядеть генерация той же самой страницы с помощью простейших шаблонов

Файл templates.php содежит описание всех необходимых шаблонов. Если посмотреть на содержимое переменных, описанных в этом файле, то можно заметить, что это просто та же самая страница, но разбитая на множество частей, между которыми должны быть вставлены данные.

Пример 10.1.2:

 

<?

// Начало заголовка страницы

$pageHeaderStart = '<HTML><head><title>';

// Конец заголовка страницы

$pageHeaderEnd = '</title><head><body>';

// Начало меню

$menuStart = '<table width="100%" border="0" cellspacing="0" cellpadding="1"><tr>';

// Конец меню

$menuEnd = '</tr></table>';

// Начало пункта меню

$menuItemCellStart = '<td>';

// Конец пункта меню

$menuItemCellEnd = '</td>';

// Начало content'а страницы

$pageContentStart = '<p>';

// Конец content'а страницы

$pageContentEnd = '</p>';

// Footer страницы

$pageFooter = '<p>(с) 2001 Вася Пупкин</p></body></HTML>';

?>

Файл index.php содержит сам код построения страницы

 

<?php

// Заголовок страницы

$title = 'Простейшая страничка';

// Содержимое меню

$menu = array(

array('page1.php','Страница 1'),

array('page2.php','Страница 2'),

array('page3.php','Страница 3')

);

// Content страницы

$content = 'Динамический content страницы';

 

// Подгружаем темплейты

include('templates.php');

// Выводим заголовок

echo $pageHeaderStart.$title.$pageHeaderEnd;

// Выводим меню

echo $menuStart;

for($i=0;$i<sizeof($menu);$i++)

echo $menuItemCellStart.'<a href="'.$menu[$i][0].'">'.$menu[$i][1].'</a>'.$menuItemCellEnd;

echo $menuEnd;

// Выводим content страницы

echo $pageContentStart.$content.$pageContentEnd;

// Выводим footer

echo $pageFooter;

?>

 

Конечно этот код выглядит просто ужасно, но основную идею "собирания" HTML кода страницы из кусочков этот пример демонстрирует достаточно хорошо.

На самом деле основная проблема приведенного выше кода состоит в том, что он не позволяет вам полностью избавиться от HTML кода внутри PHP кода, ведь здесь каждая частичка HTML кода хранится в отдельной переменной. Представьте, сколько пришлось бы иметь подобных переменных для более-менее сложной страницы. И, кроме того, несмотря на то, что непосредственно HTML код вынесен в отдельный файл, но его связь с результатами работы PHP кода жестко задана внутри самого PHP кода (ведь все объединения HTML и PHP кода жестко прописаны).

Большинство этих проблем могут быть решены путём использования несложной системы для подстановок данных в HTML-шаборны.

Основным отличием систем, основанных на подстановке данных, является то, что они позволяют, используя определенный синтаксис, определять места вставки данных в HTML-шаблоны. По сути, все имеющиеся системы работы с шаблонами основаны именно на этом принципе и единственное, что их различает – синтаксис, используемый для задания шаблонов и набор возможностей, предоставляемый системой.

Приведём одну из самых простых систем, основанных на этом принципе. Это всего лишь одна небольшая функция (чуть больше 40 строчек кода), но, тем не менее, она позволяет делать практически всё то же, что и большинство систем "среднего уровня", имеющиеся в Интернет.

Сначала – краткое описание синтаксиса для описания шаблонов, применяемых в данной системе.

 

"Ключ" для подстановки:

<Key> ::= '{'<Key name>[' '<Default value>]'}'

 

Ключом для подстановки здесь называется часть текста шаблона, которая будет впоследствии заменена на некоторые данные, переданные функции – обработчику шаблонов. Он состоит из двух основных частей: имени (уникального в пределах данного шаблона) и необязательного значения по умолчанию. Оно будет использоваться в случае, если при обработке шаблона для него не было задано значение. В случае, если значение по умолчанию также не было задано - этот ключ будет заменен на пустую строку.

Значение по умолчанию может также быть использовано для задания специальной обработки. Ниже приведены 3 различных типа синтаксиса, допустимые для значения по умолчанию:

 

<Default value> ::= <Text>

<Default value> ::= '#'<Template name>[' '<Parameter name>' '<Parameter value>]*

<Default value> ::= '!'<Function name>[' '<Parameter name>' '<Parameter value>]*

 

Как видите, тип обработки для значения по умолчанию указывается в первом символе.

Если это символ '#', то все значение рассматривается как "вставить результат обработки шаблона с именем <Template name> с заданными параметрами в качестве значения для этого ключа подстановки". Т.е. обработчик шаблонов будет вызван рекурсивно для обработки шаблона с заданным именем и заданным списком данных для подстановки, а результаты обработки этого шаблоны будут использованы в качестве значения для подстановки.

Если это символ '!', то процесс обработки похож на предыдущий, с той лишь разницей, что вместо вызова обработчика шаблонов производится вызов пользовательской функции с заданным именем и ей в качестве параметра передается массив данных, заданных в этом ключе (структура массива такая же, как и для самой функции обработки шаблонов). Результаты работы функции будут использованы в качестве значения для подстановки.

Символы, имеющие специальное значение могут быть вставлены в текст, используя их escaping sequences:

 

 

Вне ключей для подстановки

{ {l}

} {r}

Внутри ключей для подстановки

{ {{

} }}

 

Ниже приведен текст функции, которая непосредственно занимается обработкой шаблонов, используя описанный выше синтаксис.

Пример 10.1.3 (файл templates.function.php):

 

<?

// Вставка в страницу HTML кода на основе темплейтов

// Параметры:

// $template - темплейт с HTML кодом, который будет использоваться как основа

// $params - массив с данными, которые будут использоваться для подстановки.

function insertTemplate($template,$params=array())

{

// Убираем из текста темплейта все escaped символы (они будут заменены

// на необходимые значения позже) Это необходимо, чтобы облегчить задачу

// разбиения темплейтов с помощью регулярных выражений

$template = strtr($template,array('{{'=>"\x03",'}}'=>"\x04"));

// Используем регулярное выражение чтобы получить массив всех мест внутри темплейта,

// которые должны быть заменены на результаты подстановки.

preg_match_all("/\{([^\}]+)\}/i",$template,$matches);

// Если не было найдено ни одного места для подстановки -

// просто возвращаем исходный текст темплейта.

if (sizeof($matches[0])==0)

return($template);

// В этот массив мы будем собирать тексты, которые будут исползованы для

// подстановок в темплейт.

$replaces = array();

// Нам необходимо преобразовать все найденные места для подстановок внутри темплейта

// в регулярные выражения для их поиска. Тогда мы сможем впоследствии выполнить

// все подстановки одновременно, используя замену по массиву регулярных выражений.

for ($i=0;$i<sizeof($matches[0]);$i++)

$matches[0][$i] = '/'.preg_quote($matches[0][$i],'/').'/';

// Теперь нам необходимо подготовить тексты для замены

// Для этого нам необходимо обработать содержимое каждого из найденных

// мест для подстановок внутри темплейта.

for ($i=0;$i<sizeof($matches[1]);$i++)

{

// Преобразуем все escaped символы в нормальные. Символ разделения ' ' при этом

// заменяем на символ с кодом 0x01, чтобы не перепутать.

$match = strtr(strtr($matches[1][$i],array(' '=>"\x02",' '=>"\x01")),"\x02",' ');

// Проверяем, что из себя представляет строка, которую мы пытаемся обработать

if (strpos($match,"\x01")!==false)

// Эта строка содержит в себе несколько частей. Это значит, что кроме имени эта

// строка содержит какие-то параметры, которые требуют дополнительной обработки.

{

// Поскольку основная синтаксическая структура у нас состоит из 2 частей - имени

// и значения по-умолчанию - получаем эти две основные части в виде отдельных переменных

list($key,$default) = explode("\x01",$match,2);

// Исправляем regular expression для дальнейшей замены

$matches[0][$i] = "/\{$key\ [^\}]+\}/";

// Проверяем, чем является параметр, переданный внутри темплейта. Если он начинается

// с одного из специальных символов, то необходима дополнительная обработка этого значения.

// Однако это необходимо делать толлько в случае, если в переданных в функцию данных для

// замены нет текста для этой подстановки (потому что данные, переданные в качестве

// аргумента имеют более высокий приоритет).

if ((in_array($default[0],array('#','!'))) && (!isset($params[$key])))

{

// Получаем список аргументов. Первый символ отбраcываем, потому что это признак

// спеуиальной обработки и не относится к имени.

$words = explode("\x01",substr($default,1));

// Поскольку первым в полученном списке стоит имя, которое будет использоваться

// обработчиком - берем его в отдельную переменную и убираем из массива аргументов.

// Теперь в массиве $words - только список аргументов.

$name = array_shift($words);

// Проверяем, если количество аргументов - нечетное (т.е. нам необходим еще один, поскольку

// все аргументы рассматриваются как пары "имя-значение"), то добавляем пустую строку.

if ((sizeof($words)%2)!=0)

$words[] = '';

// Формируем массив параметров. Он должен быть в том же виде, в котором он передается

// в данную функцию (т.е. имя параметра задается в виде ключа ассоциативного массива).

$params = array();

for ($j=0;$j<sizeof($words);$j+=2)

$params[$words[$j]] = $words[$j+1];

if ($default[0]=='#')

// Символ '#' указывает на необходимость вставки темплейта с заданным именем

$default = insertTemplate($GLOBALS[$name],$params);

elseif ($default[0]=='!')

// Символ '#' указывает на необходимость вставки результатов работы пользовательской

// функции с заданным именем

$default = call_user_func($name,$params);

};

// Если в списке текстов для подстановки, переданных в качестве параметра в эту функцию,

// есть текст для подстановки с таким же именем, то используем его, потому что параметры,

// переданные в качестве аргумента имеют более высокий приоритет. Если же такого текста

// нет, то используем текст, имеющийся у нас в качестве значения.

$replaces[] = (isset($params[$key]))?$params[$key]:$default;

}

elseif ($match=='l')

// Эта строка - escaping для левой фигурной скобки, имеющей специальное значение.

$replaces[] = '{';

elseif ($match=='r')

// То же самое для правой фигурной скобки

$replaces[] = '}';

else

// Эта строка имеет только имя. Если в списке текстов для подстановки, переданных

// в качестве параметра в эту функцию, есть текст для подстановки с таким именем,

// то используем его, в противном случае используем в качестве замены пустую строку.

$replaces[] = (isset($params[$match]))?$params[$match]:"";

};

// Теперь у нас есть все необходимые данные и мы можем выполнить замену. Поскольку все

// строки, которые необходимо заменить в данном темплейте сконвертированы в регулярные

// выражения - необходимо просто выполнить замену по имеющимся массивам. Кроме того

// здесь же мы возвращаем нормальные значения escaped символам, которые мы убирали в начале.

return(strtr(preg_replace($matches[0],$replaces,$template),array("\x03"=>'{',"\x04"=>'}')));

};

?>

 

Теперь посмотрим, как можно сгенерировать ту же самую простейшую страничку, используя приведенную выше функцию.

Файл templates.php содежит описание всех необходимых шаблонов. Очень похоже на предыдущий вариант этого файла, но здесь в шаблонах используется описанный выше синтаксис для вставки текста.

Пример 10.1.4:

 

<?

// Основной темплейт для страницы

$tplPage = <<<HTML

<html>

<head>

<title>{title}</title>

</head>

<body>

{menu #tplMenu}

{content #tplContent}

{footer #tplFooter}

</body>

</html>

HTML;

// Темплейт для меню сайта

$tplMenu = <<<HTML

<table width="100%" border="0" cellspacing="0" cellpadding="1">

<tr>

{menuItems !createMenu}

</tr>

</table>

HTML;

// Темплейт для пункта меню для меню сайта

$tplMenuItem = <<<HTML

<td><a href="{url}">{name}</a></td>

HTML;

// Темплейт для основного content'а страницы

$tplContent = <<<HTML

<p>{content !createPageContent}</p>

HTML;

// Темплейт footer'а сайта

$tplFooter = <<<HTML

<p>{footer (с) 2001 Вася Пупкин}</p>

HTML;

?>

 

Файл index.php содержит сам код построения страницы

 

<?php

// Подгружаем все необходимые файлы

include('templates.function.php');

include('templates.php');

// Заголовок страницы

$title = 'Простейшая страничка';

// Содержимое меню

$menu = array(

array('page1.php','Страница 1'),

array('page2.php','Страница 2'),

array('page3.php','Страница 3')

);

// Content страницы

$content = 'Динамический content страницы';

// Функция генерации меню сайта. Она вызывается парсером темплейтов

// во время обработки темплейта $tplMenu.

function createMenu()

{

global $menu;

$html = '';

// Вся генерация содержимого меню сводится все к тому же вызову парсера темплейтов.

// При этом в качестве аргументов передаются данные для каждого из имеющихся пунктов меню.

foreach($menu as $item)

$html .= insertTemplate($GLOBALS['tplMenuItem'],array('url'=>$item[0],'name'=>$item[1]));

return($html);

};

// Функция генерации содержимого страницы. В нашем случае она просто возвращает переменную.

function createPageContent()

{

return($GLOBALS['content']);

};

// Как видите, после всех подготовительных шагов весь код программы сводится к одной строчке :-)

// Мы просто вызываем парсер темплейтов для обработки основного темплейта страницы, а все

// необходимые связи между темплейтами у нас прописаны непосредственно внутри них, что позволит

// впоследствии легко изменить их не меняя кода. Что, собственно, нам и требовалось.

echo insertTemplate($tplPage,array('title'=>$title));

?>

 

Как видите – код становится намного более компактным и логичным с применением шаблонов. И, кроме того, даже такая простейшая система обработки шаблонов значительно упрощает вам работу. Вы получаете возможность контролировать отдельно логику программы и отдельно – её визуальную часть, чего мы, собственно, и добивались.

Кстати, эту функцию можно применять не только для генерации HTML (все же она слишком проста для этого), а и для других целей. Например таких, как генерация e-mail. Ведь иногда бывает необходимо сгенерировать текст письма по шаблону, добавив в него какую-то информацию. Использование этой простой функции поможет вам решить эту задачу быстро и легко.

В Интернет вы можете обнаружить множество систем для работы с шаблонами разной степени "навороченности". Наиболее распространёнными являются:

· Smarty

· FastTemplate

· Cached Fast Template

· PowerTemplate

· PHemplate

· XTemplate

· ModeliXe

· ecTemplate

 

 

 








Не нашли, что искали? Воспользуйтесь поиском по сайту:



©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.