Wiki-учебник по веб-технологиям: PHP/Шаблоны ...

Главная | Каталог |

Что такое шаблоны и зачем они нужны


Оглавление документа

1. Введение


Что такое шаблон в языке программирования? Можно сказать, что шаблон – это текст с переменными внутри него. При обработке шаблона происходит замена переменных на их значения.

В одной из лекций мы уже рассматривали пример шаблона. Это был шаблон для отображения документов. Пользователь создавал строку текста, размеченного с помощью html-тегов, и вставлял в нее специальные метасимволы (вида <!имя элемента>), которые наша программа впоследствии заменяла на значения соответствующих элементов. Для чего нам был нужен такой шаблон? Чтобы, например, можно было изменить стиль отображения документа, не меняя кода программы.

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

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

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

Итак, задача:

Требуется сгенерировать web-страницу со списком статей, имеющихся в базе данных. Для простоты считаем, что статья имеет название title, автора author, краткое содержание abstract и полное содержание fulltext, которое представлено либо в виде текста в базе данных, либо в виде ссылки на файл. Список должен быть организован так, чтобы при щелчке мышью на названии статьи ее полное содержание появлялось в новом окне.

2. Шаблоны подстановки


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

Нужно придумать шаблон для этой страницы и где-то его хранить (в файле или в базе данных). Очевидно, что мы не можем придумать шаблон для всей страницы, потому что не знаем, сколько статей в базе данных. В шаблоне же мы договорились использовать только html и метасимволы <!имя элемента>. Поэтому мы можем написать только шаблон для одной строки списка, который уже программно надо преобразовать в нужное количество строк.

<li><a href="<!fulltext>"
target=new><!title></a>
(<!author>)<br><p><!abstract></p>


Кроме того, здесь есть еще одна загвоздка – с отображением ссылки на полный текст статьи. Если мы будем действовать по правилу подстановки (менять все метасимволы на их значения из базы данных), то может получиться, что вместо <!fulltext> вставим не ссылку на текст, а сам текст. То есть для этого элемента нужна дополнительная проверка перед заменой и какие-то дополнительные действия в случае, если в поле fulltext содержится текст статьи, а не ссылка на файл. Не будем усложнять себе жизнь и договоримся, что в поле fulltext всегда содержится только ссылка на файл. Тогда задачу можно решить следующим образом:

<?
$li_tmpl 
file_get_contents("tmpl.html");
// считываем шаблон строки из файла
// устанавливаем соединение и выбираем
// базу данных
$conn mysql_connect("localhost",
"nina","123")
or die(
"Cant connect");
mysql_select_db("book");
$sql "SELECT * FROM Articles";
$q mysql_query($sql,$conn);
// отправляем запрос
$num mysql_num_rows($q);
for(
$i=0$i<$num$i++){
$tmpl .= $li_tmpl;
$tmpl str_replace("<!title>",
mysql_result($q,$i,"title"),$tmpl);
$tmpl str_replace("<!author>",
mysql_result($q,$i,"author"),$tmpl);
$tmpl str_replace("<!abstract>",
mysql_result($q,$i,"abstract"),$tmpl);
$tmpl str_replace("<!fulltext>",
mysql_result($q,$i,"fulltext"),$tmpl);
}
echo 
$tmpl;
?>


Если шаблон был такой, как приведен выше, то получим примерно следующее.

  1. Лекция дает представление о том, что такое язык PHP, для чего он создавался изначально и как используется теперь, какими возможностями обладает.
  2. Рекомендации по установке и настройке web-сервера и интерпретатора PHP

В принципе метод достаточно прост и удобен, но требует дополнительных усилий программиста при возникновении задач более сложных, чем простая подстановка значений. Для решения задач, где требуется делать подстановку целых блоков или даже проверять условия, создают классы шаблонов, такие как FastTemplate и Smarty. Обсудим их подробнее.

3. Шаблоны FastTemplate


FastTemplate – это набор классов, позволяющих реализовать работу с шаблонами.

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

Что представляет собой файл шаблона FastTemplate? Это обычный html-файл, в котором могут встречаться переменные особого вида, впоследствии обрабатываемые методами класса FastTemplate.

Синтаксис переменных в шаблонах FastTemplate описывается следующим выражением: {([A-Z0–9_]+)}

Это значит, что переменная должна начинаться с фигурной скобки "{". Второй и последующие символы должны быть буквами верхнего регистра от A до Z, цифрами или символами подчеркивания. Переменная вычисляется с помощью закрывающей фигурной скобки "}".
{TITLE}
{AUTH20}
{TOP_OF_PAGE}

Пример 15.1. Вычисление переменной с помощью закрывающей фигурной скобки "}"

Как уже было сказано, основная идея FastTemplate – создание страницы с помощью вложенных шаблонов. Например, для решения нашей задачи можно создать три файла шаблона:

3. main.tpl (Этот шаблон будет выводить страницу в целом)

<html>
<head><title>{TITLE_}</title>
</head>
<body>
{MAIN}
</body>
</html>


4. list.tpl (будет описывать, как выводить список в целом)

<ul>
{LIST_ELEMENT}
</ul>


5. list_element.tpl (описывает непосредственно элемент списка)

<li><a href="{FULLTEXT}">{TITLE}</a>
({AUTHOR})
<br> <p> {ABSTRACT}


Шаблоны мы создали – работу дизайнера выполнили. Теперь нужно научиться их обрабатывать, т.е. выполнить работу программиста.

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

Перед началом работы с шаблонами FastTemplate нужно подключить этот набор классов к нашей программе. В реальной жизни набор классов FastTemplate записан в один файл, как правило, с названием class.FastTemplate.php3, поэтому подключить его можно, например, с помощью команды:

include("class.""FastTemplate"".php3");


Следующий важный шаг – это создание объекта класса FastTemplate, с которым впоследствии мы будем работать:

$tpl = new ""FastTemplate""(
"/path/to/templates");


В качестве параметра передается путь к месту, где находятся наши шаблоны.

4. Методы FastTemplate


Далее необходимо изучить методы, которые можно применять к созданному объекту класса FastTemplate. Параллельно обратим внимание, как их можно использовать для решения нашей задачи.

Для работы с FastTemplate нужно знать четыре основных метода: define, assign, parse и FastPrint.

4.1. Метод define


Синтаксис:

define( array ( ключ => значение, ключ1 => значение1, ... ))


Метод define() связывает имя файла шаблона с более коротким именем, которое можно будет использовать в программе. То есть «ключ» – это имя, которое мы будем использовать в программе для ссылки на файл шаблона, имя которого записано в строке «значение».

Реальные имена файлов шаблонов не рекомендуется использовать нигде, кроме метода define. При вызове метода define() происходит загрузка всех определенных в нем шаблонов.

$tpl->define( array (main => "main.tpl",
list_f => "list.tpl",
list_el=> "list_element.tpl" ));


Пример 15.2. Использование метода define()

Здесь мы задаем псевдонимы именам файлов шаблонов. Эти псевдонимы, т.е. переменные main, list_f и list_el, будут использоваться в программе вместо соответствующих имен файлов main.tpl, list.tpl и list_element.tpl.

4.2. Метод assign


Синтаксис:

assign( (пары ключ/значение) или ( array(пары ключ/значение) )

Метод assign() присваивает переменным значения, «ключ» – это имя переменной, а «значение» – значение, которое ей нужно присвоить.

Чтобы переменная в шаблоне была заменена значением, это значение нужно задать ей с помощью метода assign(). Согласно синтаксису этот метод можно использовать в двух различных формах. В FastTemplate есть только один массив, поэтому, если вы повторно задаете значение одному и тому же ключу, оно будет перезаписано.

$tpl->assign(array(
TITLE => "Установка и настройка ПО",
TITLE => "Введение в PHP" ));


Пример 15.3. Использование метода assign()

Здесь мы дважды устанавливаем значение переменной, доступной в файлах шаблона по имени TITLE. Эта переменная будет иметь последнее присвоенное ей значение, т.е. она равна строке «Введение в PHP».

4.3. Метод parse


Синтаксис:

parse (возвращаемая переменная, источники шаблонов)

Метод parse() – самый основной в FastTemplate. Он устанавливает значение возвращаемой переменной равным обработанным шаблонам из указанных источников. Метод может использоваться в трех формах: простой, составной и присоединяющей.

$tpl->parse(MAIN, "main");
// простая форма
$tpl->parse(MAIN, array ("list_f", "main"));
// составная форма
$tpl->parse(MAIN, ".list_el");
// присоединяющая форма

В простой форме шаблон с псевдонимом "main" загружается (если еще не был загружен), все его переменные подставляются, и результат сохраняется как значение переменной MAIN. Если переменная {MAIN} появится в более поздних шаблонах, то вместо нее будет подставлено значение, полученное в результате обработки шаблона "main". Это позволяет создавать вложенные шаблоны.

Составная форма метода **parse**() создана для того, чтобы упростить вложение шаблонов друг в друга. Следующие записи эквивалентны:
(php)
$tpl->parse(MAIN, “list_f”);
$tpl->parse(MAIN, “.main”);
(php)$tpl->parse(MAIN, array(«list_f», “main”));(php)
$tpl->Fast Print?();
/* если продолжать предыдущий пример, то эта функция напечатает значение переменной MAIN */
$tpl->Fast Print?(«MAIN»);
// эта функция сделает тоже самое
(php)
$data = $tpl->fetch(«MAIN»);
fwrite($fd, $data); // запись данных в файл
(php)
<?php
include(«class.FastTemplate.php3»); //подключаем класс
//шаблонов FastTemplate
$tpl = new FastTemplate("c:/users/nina/tasks/"); //создаем
//объект FastTemplate
//задаем псевдонимы для имен файлов шаблонов
$tpl->define( array( main => “main.tpl”,
list_f => “list.tpl”,
list_el=> “list_element.tpl” ));
// Присваиваем переменной TITLE_ значение “List of articles”
$tpl->assign(TITLE_, “List of articles”);
/* далее, как и раньше, устанавливаем соединение с базой
и получаем из нее значения нужных элементов */
$conn = mysql_connect(«localhost»,"nina","123")
or die(«Cant connect»);
mysql_select_db(«book»);
$sql = «SELECT * FROM Articles»;
$q = mysql_query($sql,$conn);
$num = mysql_num_rows($q);
for($i=0; $i<$num; $i++){
$title = mysql_result($q,$i,"title");
$author = mysql_result($q,$i,"author");
$abs = mysql_result($q,$i,"abstract");
$full = mysql_result($q,$i,"fulltext");
// присваиваем полученные значения переменным,
// использованным внутри шаблонов
$tpl->assign(array(
TITLE => $title,
AUTHOR => $author,
ABSTRACT => $abs,
FULLTEXT => $full ));
/* подставляем вместо переменных значения в шаблоне list_el и
добавляем полученное к переменной LIST_ELEMENT */
$tpl->parse(LIST_ELEMENT,".list_el");
}
//подставляем значения в шаблоны list_f и main
$tpl->parse(MAIN, array(«list_f»,"main"));
Header(«Content-type: text/plain»);
$tpl->Fast Print?(); // выводим обработанный шаблон на экран
exit;
?>
(php)
<?
require('Smarty.class?.php');
// подключаем файл с
// описанием класса Smarty
$smarty = new Smarty;
// создаем экземпляр класса Smarty
?>
(php)
<?
// подключаем файл с описанием класса
require('c:/users/my/Smarty/libs/
Smarty.class?.php');
$smarty = new Smarty;
// создаем экземпляр класса Smarty
?>
(php)
<?
define(«SMARTY_DIR»,
"c:/users/my/Smarty/libs/");
require(SMARTY_DIR."Smarty.class?.php");
$smarty = new Smarty;
?>
(php)
<?
// загружаем Smarty-библиотеку и создаем экземпляр класса
define(«SMARTY_DIR»,"c:/users/my/Smarty/libs/");
require(SMARTY_DIR."Smarty.class?.php");
$smarty = new Smarty;
// указываем, где находятся Smarty-директории
$smarty->template_dir = "c:/smarty_dirs/book/templates/";
$smarty->compile_dir = "c:/smarty_dirs/book/templates_c/";
$smarty->config_dir = "c:/smarty_dirs/book/configs/";
$smarty->cache_dir = "c:/smarty_dirs/book/cache/";
$smarty->assign(«name»,"Вася"); // присваиваем переменной
// name значение Вася
$smarty->display(«index.tpl»); // выводим обработанный
// шаблон
?>
%%

Листинг 15.4.2. index.php

В результате должны получить:
Привет, Вася!

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

Далее более подробно рассмотрим, из каких элементов могут состоять шаблоны Smarty и как их обрабатывать внутри php-скрипта.

Начнем с синтаксиса шаблонов.

5. Основной синтаксис


Smarty – не просто класс для обработки шаблонов, он определяет целый язык построения шаблонов. Мы коснемся только основных его элементов. Итак, что представляет собой шаблон Smarty? Это набор специальных конструкций (переменных, вызовов функций и методов и т.п) и html-тегов. Все элементы (теги) языка шаблонов Smarty заключаются между символами-ограничителями. По умолчанию это символы фигурных скобок "{" и "}", но их можно изменить. Все, что не заключено в такие ограничители, Smarty рассматривает как константы, не требующие обработки. В шаблоне index.tpl, приведенном выше, {$name} – это переменная, а строки «Привет," и “!" – не изменяющиеся в процессе обработки шаблона константы.

Комментарии в Smarty записываются между двумя звездочками:

{* Это комментарий. После обработки шаблона он на экране не отображается *}

Каждый Smarty тег либо выводит значение переменной, либо вызывает какую- либо функцию. Функция записывается следующим образом:

{имя_функции атрибут1="значение1" атрибут2="значение2"}

Переменные в шаблоне могут быть нескольких типов:
Например: {$first_name}

Например: {$person.last_name}

Элементы не ассоциативного массива доступны с помощью синтаксиса квадратных скобок: {имя_массива[числовой_индекс]}

Например: {$person[2]}


Например: {$person->email}


Например: {#bodyBgColor#} или {$smarty.config.bodyBgColor}

Кроме того, существует переменная {$smarty}, зарезервированная для некоторых специальных переменных шаблона, таких как переменные HTTP запроса, даты и времени, и т.п.

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

Например, чтобы перевести значение переменной {$title} в верхний регистр, нужно применить к ней модификатор upper, т.е. написать следующее: {$title|upper}

Можно использовать сразу несколько модификаторов, отделяя их друг от друга прямой вертикальной чертой. Например, {$title|upper|truncate} переведет значение переменной в верхний регистр и урежет до 80 символов.

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

6. Конфигурационные файлы


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

# глобальные переменные
pageTitle = “List of documents”
bodyBgColor = #000000
tableBgColor = #000000
rowBgColor = #00ff00
[Customer]
pageTitle = «Список статей»
Intro = "Это значение состоит из
нескольких строк. Поэтому его нужно
заключить в тройные кавычки."
# скрытая секция
[.Database]
host=localhost
db=book
user=nina
pass=123

Пример 15.5. Пример конфигурационного файла

Конфигурационный файл может состоять из нескольких разделов (секций), каждая из которых имеет имя и может загружаться отдельно от остальных секций. Имя секции заключается в квадратные скобки. Кроме секций в конфигурационном файле могут содержаться глобальные переменные – они не входят ни в одну секцию и всегда загружаются при загрузке конфигурационного файла. Если загружается какая-то одна секция, то загружаются ее переменные и глобальные переменные. Если переменная существует и как глобальная переменная, и как переменная секции, то используется переменная секции. Если вы одинаково назовете две переменные внутри одной секции, то будет использоваться последняя из них. В приведенном выше примере две секции – Customer и Database, а кроме них заданы глобальные переменные pageTitle, bodyBgColor, tableBgColor и rowBgColor.

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

Комментарии в конфигурационном файле можно обозначать символом #.

Загрузка конфигурационных файлов производится с помощью встроенной функции или метода config_load, подробнее об этом мы расскажем в следующей главе.