Рано или поздно девелоперу, создающему сайты статусом выше «сайт-визитка», приходится сталкиваться с таким понятием как «шаблоны» или «шаблонизация» визуального представления (не шаблоны проектирования). Что это такое? Механизм шаблонов позволяет отделять визуальное представление веб-приложения (по-скольку работаю только с веб-приложениями, то и рассуждать буду в этом контексте) от бизнес-логики таким образом, чтобы при изменении, например, внутренней логики попутно не приходилось переделывать всю html-верстку. На этом поприще уже давно существует несколько отдельно стоящих флагманских решений, позволяющих создавать довольно гибкие приложения в плане разделения труда дизайнеров-верстальщиков и программистов, а также предотвращать запутанность кода в больших приложениях. Описывать все их нет смысла. Это уже сделано до меня и не один раз. Помимо этого, почти каждая CMS и фрэймворк имеет собственные решения для отделения логики приложения от логики представления.
Конечно, когда речь идет о проекте в десятки тысяч строк кода, когда у заказчика есть возможность нанять и программиста, и верстальщика, то и функционал шаблонов будет только пользой для всех участников проекта. Но когда разработчик в простецкий сайт в 3 страницы начинает втуливать Smarty, это ИМХО уже перебор. В таких случаях я люблю вспоминать выражение Джорджа Шлоснейгла из его замечательной книги «Профессиональное программирование на PHP» – «попытка убить муху молтком».
Действительно, встраивая все тот же Smarty в весьма простой по функционалу сайт, разработчик попросту тратит время. А время, как известно, — деньги. Да и в большинстве случаев заказчику безразлично на каком шаблонизаторе будет работать его сайт. Заказчик больше печется о затраченном времени.
Что же делать, если сайт не «визитка», но и не второй Amazon? Лично я считаю, что в этом случае оптимальное решение проблемы — воспользоваться своей самописной системой шаблонов, весь функционал которой, заточен только для решения узкого круга задач, необходимых для текущего ресурса. Впоследствии вы, возможно, выведите свою «формулу» универсального шаблонизатора с неким минимальным набором функций, расширяемую по мере необходимости в отдельно взятом проекте.
Может показаться, что автор сей статьи весьма скептически относится к Smarty и другим шаблонизаторам. Это не так. Я довольно долго работал с проектом, в котором роль шаблонизатора выполнял все тот же Smarty. И хочу заметить, мне весьма понравилось использование этой системы шаблонов в контексте обширного по функционалу проекта.
Но вернемся к пробелеме разделения визуального от абстракции. Каким минимальным требованиям должен отвечать шаблонизатор в среднем проекте?
- Возможность назначать переменные шаблону
- Отдельное пространство имен переменных для отдельно взятого html-шаблона
- Возможность использования одного шаблона для общего каркаса страницы во избежание повторения конструкций вида require 'header.tpl';… require 'footer.tpl'; в каждом файле
К слову, «средний» проект — это некий эталон измерения сложности веб-приложения по моей личной шкале и соотвествует примерно следующим критериям:
- Проект является интернет-магазином или социальным сообществом
- 10-20 типов страниц. Подчеркиваю — НЕ страниц, а типов страниц. Например: страница описания товара. Т.е. html-шаблон для этого типа страниц будет один, но самих страниц, когда каталог заполнится контентом будет много
У каждого девелопера эта шкала своя, так что в этом вопросе прошу строго не судить.
Перейдем от слов к делу.
Рассмотрим простейший класс, который состоит всего из трех методов.
<?php
class Template {
private $_tmpl;
private $_vars = array();
public function __construct($filename) {
$this->_tmpl = $filename;
}
public function assign($name, $value) {
$this->_vars[$name] = $value;
}
public function render() {
if (count($this->_vars) > 0) {
extract($this->_vars);
}
$tmplPath = "../templates/{$this->_tmpl}.tpl";
if (file_exists($tmplPath)) {
require $tmplPath;
} else {
throw new Exception("Шаблон <strong>{$this->_tmpl}</strong> не найден");
}
}
}
Давайте рассмотрим пример с применением этого класса. Создадим следующую структуру каталогов:
/wwwroot
|
— /classes
| — Template.php
— /templates
| — Main.tpl
| — Catalog.tpl
| — Product.tpl
| — Index.tpl
| — 404.tpl
|-- index.php
Main.tpl
<!-- Общий каркас страницы -->
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<?php echo $content ?>
</body>
</html>
Catalog.tpl
<!-- Это шаблон страницы каталога -->
<p>Каталог №<?php echo $ID ?></p>
Product.tpl
<!-- Это шаблон страницы продукта -->
<p>Страница описания продукта №<?php echo $ID ?></p>
Index.tpl
<!-- Это главная страница -->
<p>Это главная страница сайта</p>
404.tpl
<!-- Это шаблон страницы 404-й ошибки -->
<p>Страница не найдена!</p>
index.php
/**
* Буферизация вывода.
* Все, что будет выводиться echo-м или print-ом, будет попадать в буфер, а не в браузер пользователю.
*/
ob_start();
// Подключаем шаблонизатор
require dirname(__FILE__).'/classes/Template.php';
// Производим проверку маршрутизации и включаем необходимые шаблоны
// Если не один из шаблонов не найден, отправляем клиенту код ошибки и показываем шаблон 404.tpl
// Если маршрут не задан, выводим главную страницу
if (isset($_GET['route']) && $_GET['route'] == 'catalog') {
$tmpl = new Template('Catalog');
$tmpl->assign('ID', $_GET['ID']);
$tmpl->render();
} else if ($_GET['route']) && $_GET['route'] == 'product') {
$tmpl = new Template('Catalog');
$tmpl->assign('ID', $_GET['ID']);
$tmpl->render();
} else if (!isset($_GET['route'])) {
$tmpl = new Template('Index');
$tmpl->render();
} else {
header("HTTP/1.0 404 Not Found");
$tmpl = new Template('404');
$tmpl->render();
}
// Получаем содержимое буфера
$content = ob_get_clean();
// Инициализируем шаблон каркаса страницы и выводим ранее сгенерированное содержимое
$tmpl = new Template('Main');
$tmpl->assign('content', $content);
$tmpl->render();
Как видно из примера, содержимое страниц catalog и product изменяется в зависимости от значения $_GET['ID']. Т.о. мы получили два типа шаблонов и неограниченное количество страниц, генерируемых приложением из этих шаблонов.
Вывод: не стремитесь во всех проектах, которыми вы занимаетесь, использовать навороченные библиотеки шаблонизаторов, предоставляющих большое обилие всевозможных инструментов, в большинстве случаев не используемых в должном объеме. Лучше всего написать свое решение, которое поможет сэкономить время, системные ресурсы, а главное — нервы останутся в порядке.
Спасибо за внимание.
Автор: snager